Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(381)

Side by Side Diff: infra/tools/cros_pin/pinfile.py

Issue 1403313002: Added `cros_pin` CrOS pin-bump tool. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: contextmanager, cleanup. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import collections
6 import contextlib
7 import json
8 import re
9
10 from infra.libs.gitiles import gitiles
11 from infra.tools.cros_pin.logger import LOGGER
12
13 class InvalidPinError(Exception):
14 pass
15
16 class ReadOnlyError(Exception):
17 pass
18
19
20 # Named Chromite pins to their checkout-relative paths.
21 Config = collections.namedtuple('Config',
22 ('name', 'base', 'json_subpath', 'masters'))
23
24
25 EXTERNAL = Config(
26 'external',
27 ('build',),
28 ('scripts', 'common', 'cros_chromite_pins.json'),
29 ('chromiumos',))
30
31
32 INTERNAL = Config(
33 'internal',
34 ('build_internal',),
35 ('scripts', 'common_internal', 'cros_chromite_internal_pins.json'),
36 ('chromeos', 'chromeos_release'))
37
38
39 PinUpdate = collections.namedtuple('PinUpdate',
40 ('name', 'fr', 'to'))
41
42
43 class Editor(object):
44
45 # Regular expression to match a Git commit (SHA1)
46 RE_COMMIT_SHA1 = re.compile(r'^[a-fA-F0-9]{40}$')
47
48 def __init__(self, c, chromite_repo=None, validate=True):
49 self._c = c
50 self._gitiles = gitiles.Repository(chromite_repo)
51 self._validate = validate
52
53 def load(self, pin):
54 return self.File(self, pin)
55
56 def get_commit(self, branch):
57 try:
58 return self._gitiles.ref_info(branch)['commit']
59 except gitiles.GitilesError:
60 raise InvalidPinError("Pin ref [%s] does not exist." % (branch,))
61
62 def validate_pin(self, ref):
63 if not self.RE_COMMIT_SHA1.match(ref):
64 raise InvalidPinError("Not a valid SHA1 hash")
65 self.get_commit(ref)
66
67 class File(object):
68 def __init__(self, editor, pin):
69 self._editor = editor
70 self._pin = pin
71 self._path = self._editor._c.subpath(*(pin.base + pin.json_subpath))
72
73 @contextlib.contextmanager
74 def edit(self):
75 d = self.load()
76 orig = d.copy()
77 try:
78 yield d
79 finally:
80 if d != orig:
81 self.save(**d)
82
83 def load(self):
84 with open(self._path, 'r') as fd:
85 return json.load(fd)
86
87 def save(self, **pins):
88 for k, v in pins.iteritems():
89 assert isinstance(k, basestring)
90 assert isinstance(v, basestring)
91 LOGGER.debug('Writing pin file [%s]: %s', self._path, pins)
92 with open(self._path, 'w') as fd:
93 json.dump(pins, fd, indent=2, sort_keys=True)
94
95
96 def update(self, pin_name, create=False, version=None):
97 """Updates a single pin value."""
98 if not version:
99 LOGGER.debug('Resolving version for pin [%s]', pin_name)
100 version = self._editor.get_commit(pin_name)
101 elif self._editor._validate:
102 LOGGER.debug('Validating pin [%s]', pin_name)
103 self._editor.validate_pin(version)
104
105 with self.edit() as pins:
106 current = pins.get(pin_name)
107 if current == version:
108 LOGGER.warning('Pin [%s.%s] is already at version [%s]',
109 self._pin.name, pin_name, current)
110 return None
111
112 LOGGER.info('Updating pin [%s.%s]: [%s] => [%s]',
113 self._pin.name, pin_name, current, version)
114 if not (current or create):
115 raise ReadOnlyError("Pin does not exist [%s]" % (pin_name,))
116 pins[pin_name] = version
117 return PinUpdate(pin_name, current, version)
118 return None
119
120 def remove(self, pin_name):
121 """Removes a single pin from the pin list."""
122 with self.edit() as pins:
123 cur = pins.pop(pin_name, None)
124 if cur is None:
125 return None
126 return PinUpdate(pin_name, cur, None)
127
128 def iterpins(self):
129 """Returns a list of pins."""
130 return self.load().iteritems()
OLDNEW
« infra/tools/cros_pin/cros_pin.py ('K') | « infra/tools/cros_pin/logger.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698