diff options
Diffstat (limited to 'subcmds')
-rw-r--r-- | subcmds/__init__.py | 4 | ||||
-rw-r--r-- | subcmds/branches.py | 5 | ||||
-rw-r--r-- | subcmds/cherry_pick.py | 2 | ||||
-rw-r--r-- | subcmds/forall.py | 21 | ||||
-rw-r--r-- | subcmds/help.py | 12 | ||||
-rw-r--r-- | subcmds/info.py | 12 | ||||
-rw-r--r-- | subcmds/init.py | 30 | ||||
-rw-r--r-- | subcmds/list.py | 33 | ||||
-rw-r--r-- | subcmds/overview.py | 2 | ||||
-rw-r--r-- | subcmds/rebase.py | 2 | ||||
-rw-r--r-- | subcmds/stage.py | 8 | ||||
-rw-r--r-- | subcmds/status.py | 12 | ||||
-rw-r--r-- | subcmds/sync.py | 55 | ||||
-rw-r--r-- | subcmds/upload.py | 56 |
14 files changed, 189 insertions, 65 deletions
diff --git a/subcmds/__init__.py b/subcmds/__init__.py index 1fac802e..84efb4de 100644 --- a/subcmds/__init__.py +++ b/subcmds/__init__.py | |||
@@ -38,8 +38,8 @@ for py in os.listdir(my_dir): | |||
38 | try: | 38 | try: |
39 | cmd = getattr(mod, clsn)() | 39 | cmd = getattr(mod, clsn)() |
40 | except AttributeError: | 40 | except AttributeError: |
41 | raise SyntaxError, '%s/%s does not define class %s' % ( | 41 | raise SyntaxError('%s/%s does not define class %s' % ( |
42 | __name__, py, clsn) | 42 | __name__, py, clsn)) |
43 | 43 | ||
44 | name = name.replace('_', '-') | 44 | name = name.replace('_', '-') |
45 | cmd.NAME = name | 45 | cmd.NAME = name |
diff --git a/subcmds/branches.py b/subcmds/branches.py index 06d45abe..c2e7c4b9 100644 --- a/subcmds/branches.py +++ b/subcmds/branches.py | |||
@@ -98,14 +98,13 @@ is shown, then the branch appears in all projects. | |||
98 | project_cnt = len(projects) | 98 | project_cnt = len(projects) |
99 | 99 | ||
100 | for project in projects: | 100 | for project in projects: |
101 | for name, b in project.GetBranches().iteritems(): | 101 | for name, b in project.GetBranches().items(): |
102 | b.project = project | 102 | b.project = project |
103 | if name not in all_branches: | 103 | if name not in all_branches: |
104 | all_branches[name] = BranchInfo(name) | 104 | all_branches[name] = BranchInfo(name) |
105 | all_branches[name].add(b) | 105 | all_branches[name].add(b) |
106 | 106 | ||
107 | names = all_branches.keys() | 107 | names = list(sorted(all_branches)) |
108 | names.sort() | ||
109 | 108 | ||
110 | if not names: | 109 | if not names: |
111 | print(' (no branches)', file=sys.stderr) | 110 | print(' (no branches)', file=sys.stderr) |
diff --git a/subcmds/cherry_pick.py b/subcmds/cherry_pick.py index 01b97e07..520e4c32 100644 --- a/subcmds/cherry_pick.py +++ b/subcmds/cherry_pick.py | |||
@@ -81,7 +81,7 @@ change id will be added. | |||
81 | sys.exit(1) | 81 | sys.exit(1) |
82 | 82 | ||
83 | else: | 83 | else: |
84 | print('NOTE: When committing (please see above) and editing the commit' | 84 | print('NOTE: When committing (please see above) and editing the commit ' |
85 | 'message, please remove the old Change-Id-line and add:') | 85 | 'message, please remove the old Change-Id-line and add:') |
86 | print(self._GetReference(sha1), file=sys.stderr) | 86 | print(self._GetReference(sha1), file=sys.stderr) |
87 | print(file=sys.stderr) | 87 | print(file=sys.stderr) |
diff --git a/subcmds/forall.py b/subcmds/forall.py index 4c1c9ff8..e2a420a9 100644 --- a/subcmds/forall.py +++ b/subcmds/forall.py | |||
@@ -42,10 +42,14 @@ class Forall(Command, MirrorSafeCommand): | |||
42 | helpSummary = "Run a shell command in each project" | 42 | helpSummary = "Run a shell command in each project" |
43 | helpUsage = """ | 43 | helpUsage = """ |
44 | %prog [<project>...] -c <command> [<arg>...] | 44 | %prog [<project>...] -c <command> [<arg>...] |
45 | %prog -r str1 [str2] ... -c <command> [<arg>...]" | ||
45 | """ | 46 | """ |
46 | helpDescription = """ | 47 | helpDescription = """ |
47 | Executes the same shell command in each project. | 48 | Executes the same shell command in each project. |
48 | 49 | ||
50 | The -r option allows running the command only on projects matching | ||
51 | regex or wildcard expression. | ||
52 | |||
49 | Output Formatting | 53 | Output Formatting |
50 | ----------------- | 54 | ----------------- |
51 | 55 | ||
@@ -103,6 +107,9 @@ without iterating through the remaining projects. | |||
103 | setattr(parser.values, option.dest, list(parser.rargs)) | 107 | setattr(parser.values, option.dest, list(parser.rargs)) |
104 | while parser.rargs: | 108 | while parser.rargs: |
105 | del parser.rargs[0] | 109 | del parser.rargs[0] |
110 | p.add_option('-r', '--regex', | ||
111 | dest='regex', action='store_true', | ||
112 | help="Execute the command only on projects matching regex or wildcard expression") | ||
106 | p.add_option('-c', '--command', | 113 | p.add_option('-c', '--command', |
107 | help='Command (and arguments) to execute', | 114 | help='Command (and arguments) to execute', |
108 | dest='command', | 115 | dest='command', |
@@ -166,7 +173,12 @@ without iterating through the remaining projects. | |||
166 | rc = 0 | 173 | rc = 0 |
167 | first = True | 174 | first = True |
168 | 175 | ||
169 | for project in self.GetProjects(args): | 176 | if not opt.regex: |
177 | projects = self.GetProjects(args) | ||
178 | else: | ||
179 | projects = self.FindProjects(args) | ||
180 | |||
181 | for project in projects: | ||
170 | env = os.environ.copy() | 182 | env = os.environ.copy() |
171 | def setenv(name, val): | 183 | def setenv(name, val): |
172 | if val is None: | 184 | if val is None: |
@@ -248,7 +260,12 @@ without iterating through the remaining projects. | |||
248 | first = False | 260 | first = False |
249 | else: | 261 | else: |
250 | out.nl() | 262 | out.nl() |
251 | out.project('project %s/', project.relpath) | 263 | |
264 | if mirror: | ||
265 | project_header_path = project.name | ||
266 | else: | ||
267 | project_header_path = project.relpath | ||
268 | out.project('project %s/', project_header_path) | ||
252 | out.nl() | 269 | out.nl() |
253 | out.flush() | 270 | out.flush() |
254 | if errbuf: | 271 | if errbuf: |
diff --git a/subcmds/help.py b/subcmds/help.py index 15aab7f9..4aa3f863 100644 --- a/subcmds/help.py +++ b/subcmds/help.py | |||
@@ -34,8 +34,7 @@ Displays detailed usage information about a command. | |||
34 | def _PrintAllCommands(self): | 34 | def _PrintAllCommands(self): |
35 | print('usage: repo COMMAND [ARGS]') | 35 | print('usage: repo COMMAND [ARGS]') |
36 | print('The complete list of recognized repo commands are:') | 36 | print('The complete list of recognized repo commands are:') |
37 | commandNames = self.commands.keys() | 37 | commandNames = list(sorted(self.commands)) |
38 | commandNames.sort() | ||
39 | 38 | ||
40 | maxlen = 0 | 39 | maxlen = 0 |
41 | for name in commandNames: | 40 | for name in commandNames: |
@@ -49,16 +48,15 @@ Displays detailed usage information about a command. | |||
49 | except AttributeError: | 48 | except AttributeError: |
50 | summary = '' | 49 | summary = '' |
51 | print(fmt % (name, summary)) | 50 | print(fmt % (name, summary)) |
52 | print("See 'repo help <command>' for more information on a" | 51 | print("See 'repo help <command>' for more information on a " |
53 | 'specific command.') | 52 | 'specific command.') |
54 | 53 | ||
55 | def _PrintCommonCommands(self): | 54 | def _PrintCommonCommands(self): |
56 | print('usage: repo COMMAND [ARGS]') | 55 | print('usage: repo COMMAND [ARGS]') |
57 | print('The most commonly used repo commands are:') | 56 | print('The most commonly used repo commands are:') |
58 | commandNames = [name | 57 | commandNames = list(sorted([name |
59 | for name in self.commands.keys() | 58 | for name, command in self.commands.items() |
60 | if self.commands[name].common] | 59 | if command.common])) |
61 | commandNames.sort() | ||
62 | 60 | ||
63 | maxlen = 0 | 61 | maxlen = 0 |
64 | for name in commandNames: | 62 | for name in commandNames: |
diff --git a/subcmds/info.py b/subcmds/info.py index 8fb363f3..d42860ae 100644 --- a/subcmds/info.py +++ b/subcmds/info.py | |||
@@ -27,7 +27,7 @@ class Info(PagedCommand): | |||
27 | helpSummary = "Get info on the manifest branch, current branch or unmerged branches" | 27 | helpSummary = "Get info on the manifest branch, current branch or unmerged branches" |
28 | helpUsage = "%prog [-dl] [-o [-b]] [<project>...]" | 28 | helpUsage = "%prog [-dl] [-o [-b]] [<project>...]" |
29 | 29 | ||
30 | def _Options(self, p, show_smart=True): | 30 | def _Options(self, p): |
31 | p.add_option('-d', '--diff', | 31 | p.add_option('-d', '--diff', |
32 | dest='all', action='store_true', | 32 | dest='all', action='store_true', |
33 | help="show full info and commit diff including remote branches") | 33 | help="show full info and commit diff including remote branches") |
@@ -53,7 +53,10 @@ class Info(PagedCommand): | |||
53 | 53 | ||
54 | self.opt = opt | 54 | self.opt = opt |
55 | 55 | ||
56 | mergeBranch = self.manifest.manifestProject.config.GetBranch("default").merge | 56 | manifestConfig = self.manifest.manifestProject.config |
57 | mergeBranch = manifestConfig.GetBranch("default").merge | ||
58 | manifestGroups = (manifestConfig.GetString('manifest.groups') | ||
59 | or 'all,-notdefault') | ||
57 | 60 | ||
58 | self.heading("Manifest branch: ") | 61 | self.heading("Manifest branch: ") |
59 | self.headtext(self.manifest.default.revisionExpr) | 62 | self.headtext(self.manifest.default.revisionExpr) |
@@ -61,6 +64,9 @@ class Info(PagedCommand): | |||
61 | self.heading("Manifest merge branch: ") | 64 | self.heading("Manifest merge branch: ") |
62 | self.headtext(mergeBranch) | 65 | self.headtext(mergeBranch) |
63 | self.out.nl() | 66 | self.out.nl() |
67 | self.heading("Manifest groups: ") | ||
68 | self.headtext(manifestGroups) | ||
69 | self.out.nl() | ||
64 | 70 | ||
65 | self.printSeparator() | 71 | self.printSeparator() |
66 | 72 | ||
@@ -157,7 +163,7 @@ class Info(PagedCommand): | |||
157 | all_branches = [] | 163 | all_branches = [] |
158 | for project in self.GetProjects(args): | 164 | for project in self.GetProjects(args): |
159 | br = [project.GetUploadableBranch(x) | 165 | br = [project.GetUploadableBranch(x) |
160 | for x in project.GetBranches().keys()] | 166 | for x in project.GetBranches()] |
161 | br = [x for x in br if x] | 167 | br = [x for x in br if x] |
162 | if self.opt.current_branch: | 168 | if self.opt.current_branch: |
163 | br = [x for x in br if x.name == project.CurrentBranch] | 169 | br = [x for x in br if x.name == project.CurrentBranch] |
diff --git a/subcmds/init.py b/subcmds/init.py index 11312601..a44fb7a9 100644 --- a/subcmds/init.py +++ b/subcmds/init.py | |||
@@ -20,6 +20,15 @@ import re | |||
20 | import shutil | 20 | import shutil |
21 | import sys | 21 | import sys |
22 | 22 | ||
23 | from pyversion import is_python3 | ||
24 | if is_python3(): | ||
25 | import urllib.parse | ||
26 | else: | ||
27 | import imp | ||
28 | import urlparse | ||
29 | urllib = imp.new_module('urllib') | ||
30 | urllib.parse = urlparse.urlparse | ||
31 | |||
23 | from color import Coloring | 32 | from color import Coloring |
24 | from command import InteractiveCommand, MirrorSafeCommand | 33 | from command import InteractiveCommand, MirrorSafeCommand |
25 | from error import ManifestParseError | 34 | from error import ManifestParseError |
@@ -91,8 +100,9 @@ to update the working directory files. | |||
91 | dest='depth', | 100 | dest='depth', |
92 | help='create a shallow clone with given depth; see git clone') | 101 | help='create a shallow clone with given depth; see git clone') |
93 | g.add_option('-g', '--groups', | 102 | g.add_option('-g', '--groups', |
94 | dest='groups', default='all,-notdefault', | 103 | dest='groups', default='default', |
95 | help='restrict manifest projects to ones with a specified group', | 104 | help='restrict manifest projects to ones with specified ' |
105 | 'group(s) [default|all|G1,G2,G3|G4,-G5,-G6]', | ||
96 | metavar='GROUP') | 106 | metavar='GROUP') |
97 | g.add_option('-p', '--platform', | 107 | g.add_option('-p', '--platform', |
98 | dest='platform', default='auto', | 108 | dest='platform', default='auto', |
@@ -134,7 +144,19 @@ to update the working directory files. | |||
134 | if not opt.quiet: | 144 | if not opt.quiet: |
135 | print('Get %s' % GitConfig.ForUser().UrlInsteadOf(opt.manifest_url), | 145 | print('Get %s' % GitConfig.ForUser().UrlInsteadOf(opt.manifest_url), |
136 | file=sys.stderr) | 146 | file=sys.stderr) |
137 | m._InitGitDir() | 147 | |
148 | # The manifest project object doesn't keep track of the path on the | ||
149 | # server where this git is located, so let's save that here. | ||
150 | mirrored_manifest_git = None | ||
151 | if opt.reference: | ||
152 | manifest_git_path = urllib.parse(opt.manifest_url).path[1:] | ||
153 | mirrored_manifest_git = os.path.join(opt.reference, manifest_git_path) | ||
154 | if not mirrored_manifest_git.endswith(".git"): | ||
155 | mirrored_manifest_git += ".git" | ||
156 | if not os.path.exists(mirrored_manifest_git): | ||
157 | mirrored_manifest_git = os.path.join(opt.reference + '/.repo/manifests.git') | ||
158 | |||
159 | m._InitGitDir(mirror_git=mirrored_manifest_git) | ||
138 | 160 | ||
139 | if opt.manifest_branch: | 161 | if opt.manifest_branch: |
140 | m.revisionExpr = opt.manifest_branch | 162 | m.revisionExpr = opt.manifest_branch |
@@ -169,7 +191,7 @@ to update the working directory files. | |||
169 | 191 | ||
170 | groups = [x for x in groups if x] | 192 | groups = [x for x in groups if x] |
171 | groupstr = ','.join(groups) | 193 | groupstr = ','.join(groups) |
172 | if opt.platform == 'auto' and groupstr == 'all,-notdefault,platform-' + platform.system().lower(): | 194 | if opt.platform == 'auto' and groupstr == 'default,platform-' + platform.system().lower(): |
173 | groupstr = None | 195 | groupstr = None |
174 | m.config.SetString('manifest.groups', groupstr) | 196 | m.config.SetString('manifest.groups', groupstr) |
175 | 197 | ||
diff --git a/subcmds/list.py b/subcmds/list.py index 0d5c27f7..945c28d8 100644 --- a/subcmds/list.py +++ b/subcmds/list.py | |||
@@ -14,7 +14,7 @@ | |||
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | 16 | from __future__ import print_function |
17 | import re | 17 | import sys |
18 | 18 | ||
19 | from command import Command, MirrorSafeCommand | 19 | from command import Command, MirrorSafeCommand |
20 | 20 | ||
@@ -31,13 +31,19 @@ List all projects; pass '.' to list the project for the cwd. | |||
31 | This is similar to running: repo forall -c 'echo "$REPO_PATH : $REPO_PROJECT"'. | 31 | This is similar to running: repo forall -c 'echo "$REPO_PATH : $REPO_PROJECT"'. |
32 | """ | 32 | """ |
33 | 33 | ||
34 | def _Options(self, p, show_smart=True): | 34 | def _Options(self, p): |
35 | p.add_option('-r', '--regex', | 35 | p.add_option('-r', '--regex', |
36 | dest='regex', action='store_true', | 36 | dest='regex', action='store_true', |
37 | help="Filter the project list based on regex or wildcard matching of strings") | 37 | help="Filter the project list based on regex or wildcard matching of strings") |
38 | p.add_option('-f', '--fullpath', | 38 | p.add_option('-f', '--fullpath', |
39 | dest='fullpath', action='store_true', | 39 | dest='fullpath', action='store_true', |
40 | help="Display the full work tree path instead of the relative path") | 40 | help="Display the full work tree path instead of the relative path") |
41 | p.add_option('-n', '--name-only', | ||
42 | dest='name_only', action='store_true', | ||
43 | help="Display only the name of the repository") | ||
44 | p.add_option('-p', '--path-only', | ||
45 | dest='path_only', action='store_true', | ||
46 | help="Display only the path of the repository") | ||
41 | 47 | ||
42 | def Execute(self, opt, args): | 48 | def Execute(self, opt, args): |
43 | """List all projects and the associated directories. | 49 | """List all projects and the associated directories. |
@@ -50,6 +56,11 @@ This is similar to running: repo forall -c 'echo "$REPO_PATH : $REPO_PROJECT"'. | |||
50 | opt: The options. | 56 | opt: The options. |
51 | args: Positional args. Can be a list of projects to list, or empty. | 57 | args: Positional args. Can be a list of projects to list, or empty. |
52 | """ | 58 | """ |
59 | |||
60 | if opt.fullpath and opt.name_only: | ||
61 | print('error: cannot combine -f and -n', file=sys.stderr) | ||
62 | sys.exit(1) | ||
63 | |||
53 | if not opt.regex: | 64 | if not opt.regex: |
54 | projects = self.GetProjects(args) | 65 | projects = self.GetProjects(args) |
55 | else: | 66 | else: |
@@ -62,18 +73,12 @@ This is similar to running: repo forall -c 'echo "$REPO_PATH : $REPO_PROJECT"'. | |||
62 | 73 | ||
63 | lines = [] | 74 | lines = [] |
64 | for project in projects: | 75 | for project in projects: |
65 | lines.append("%s : %s" % (_getpath(project), project.name)) | 76 | if opt.name_only and not opt.path_only: |
77 | lines.append("%s" % ( project.name)) | ||
78 | elif opt.path_only and not opt.name_only: | ||
79 | lines.append("%s" % (_getpath(project))) | ||
80 | else: | ||
81 | lines.append("%s : %s" % (_getpath(project), project.name)) | ||
66 | 82 | ||
67 | lines.sort() | 83 | lines.sort() |
68 | print('\n'.join(lines)) | 84 | print('\n'.join(lines)) |
69 | |||
70 | def FindProjects(self, args): | ||
71 | result = [] | ||
72 | for project in self.GetProjects(''): | ||
73 | for arg in args: | ||
74 | pattern = re.compile(r'%s' % arg, re.IGNORECASE) | ||
75 | if pattern.search(project.name) or pattern.search(project.relpath): | ||
76 | result.append(project) | ||
77 | break | ||
78 | result.sort(key=lambda project: project.relpath) | ||
79 | return result | ||
diff --git a/subcmds/overview.py b/subcmds/overview.py index 418459ae..eed8cf20 100644 --- a/subcmds/overview.py +++ b/subcmds/overview.py | |||
@@ -42,7 +42,7 @@ are displayed. | |||
42 | all_branches = [] | 42 | all_branches = [] |
43 | for project in self.GetProjects(args): | 43 | for project in self.GetProjects(args): |
44 | br = [project.GetUploadableBranch(x) | 44 | br = [project.GetUploadableBranch(x) |
45 | for x in project.GetBranches().keys()] | 45 | for x in project.GetBranches()] |
46 | br = [x for x in br if x] | 46 | br = [x for x in br if x] |
47 | if opt.current_branch: | 47 | if opt.current_branch: |
48 | br = [x for x in br if x.name == project.CurrentBranch] | 48 | br = [x for x in br if x.name == project.CurrentBranch] |
diff --git a/subcmds/rebase.py b/subcmds/rebase.py index 06cda22c..b9a7774d 100644 --- a/subcmds/rebase.py +++ b/subcmds/rebase.py | |||
@@ -68,7 +68,7 @@ branch but need to incorporate new upstream changes "underneath" them. | |||
68 | cb = project.CurrentBranch | 68 | cb = project.CurrentBranch |
69 | if not cb: | 69 | if not cb: |
70 | if one_project: | 70 | if one_project: |
71 | print("error: project %s has a detatched HEAD" % project.relpath, | 71 | print("error: project %s has a detached HEAD" % project.relpath, |
72 | file=sys.stderr) | 72 | file=sys.stderr) |
73 | return -1 | 73 | return -1 |
74 | # ignore branches with detatched HEADs | 74 | # ignore branches with detatched HEADs |
diff --git a/subcmds/stage.py b/subcmds/stage.py index ff15ee0c..28849764 100644 --- a/subcmds/stage.py +++ b/subcmds/stage.py | |||
@@ -49,7 +49,7 @@ The '%prog' command stages files to prepare the next commit. | |||
49 | self.Usage() | 49 | self.Usage() |
50 | 50 | ||
51 | def _Interactive(self, opt, args): | 51 | def _Interactive(self, opt, args): |
52 | all_projects = filter(lambda x: x.IsDirty(), self.GetProjects(args)) | 52 | all_projects = [p for p in self.GetProjects(args) if p.IsDirty()] |
53 | if not all_projects: | 53 | if not all_projects: |
54 | print('no projects have uncommitted modifications', file=sys.stderr) | 54 | print('no projects have uncommitted modifications', file=sys.stderr) |
55 | return | 55 | return |
@@ -98,9 +98,9 @@ The '%prog' command stages files to prepare the next commit. | |||
98 | _AddI(all_projects[a_index - 1]) | 98 | _AddI(all_projects[a_index - 1]) |
99 | continue | 99 | continue |
100 | 100 | ||
101 | p = filter(lambda x: x.name == a or x.relpath == a, all_projects) | 101 | projects = [p for p in all_projects if a in [p.name, p.relpath]] |
102 | if len(p) == 1: | 102 | if len(projects) == 1: |
103 | _AddI(p[0]) | 103 | _AddI(projects[0]) |
104 | continue | 104 | continue |
105 | print('Bye.') | 105 | print('Bye.') |
106 | 106 | ||
diff --git a/subcmds/status.py b/subcmds/status.py index cce00c81..41c4429a 100644 --- a/subcmds/status.py +++ b/subcmds/status.py | |||
@@ -21,10 +21,16 @@ except ImportError: | |||
21 | import dummy_threading as _threading | 21 | import dummy_threading as _threading |
22 | 22 | ||
23 | import glob | 23 | import glob |
24 | |||
25 | from pyversion import is_python3 | ||
26 | if is_python3(): | ||
27 | import io | ||
28 | else: | ||
29 | import StringIO as io | ||
30 | |||
24 | import itertools | 31 | import itertools |
25 | import os | 32 | import os |
26 | import sys | 33 | import sys |
27 | import StringIO | ||
28 | 34 | ||
29 | from color import Coloring | 35 | from color import Coloring |
30 | 36 | ||
@@ -142,7 +148,7 @@ the following meanings: | |||
142 | for project in all_projects: | 148 | for project in all_projects: |
143 | sem.acquire() | 149 | sem.acquire() |
144 | 150 | ||
145 | class BufList(StringIO.StringIO): | 151 | class BufList(io.StringIO): |
146 | def dump(self, ostream): | 152 | def dump(self, ostream): |
147 | for entry in self.buflist: | 153 | for entry in self.buflist: |
148 | ostream.write(entry) | 154 | ostream.write(entry) |
@@ -182,7 +188,7 @@ the following meanings: | |||
182 | try: | 188 | try: |
183 | os.chdir(self.manifest.topdir) | 189 | os.chdir(self.manifest.topdir) |
184 | 190 | ||
185 | outstring = StringIO.StringIO() | 191 | outstring = io.StringIO() |
186 | self._FindOrphans(glob.glob('.*') + \ | 192 | self._FindOrphans(glob.glob('.*') + \ |
187 | glob.glob('*'), \ | 193 | glob.glob('*'), \ |
188 | proj_dirs, proj_dirs_parents, outstring) | 194 | proj_dirs, proj_dirs_parents, outstring) |
diff --git a/subcmds/sync.py b/subcmds/sync.py index 5c369a74..e9d52b7b 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py | |||
@@ -24,8 +24,19 @@ import socket | |||
24 | import subprocess | 24 | import subprocess |
25 | import sys | 25 | import sys |
26 | import time | 26 | import time |
27 | import urlparse | 27 | |
28 | import xmlrpclib | 28 | from pyversion import is_python3 |
29 | if is_python3(): | ||
30 | import urllib.parse | ||
31 | import xmlrpc.client | ||
32 | else: | ||
33 | import imp | ||
34 | import urlparse | ||
35 | import xmlrpclib | ||
36 | urllib = imp.new_module('urllib') | ||
37 | urllib.parse = urlparse | ||
38 | xmlrpc = imp.new_module('xmlrpc') | ||
39 | xmlrpc.client = xmlrpclib | ||
29 | 40 | ||
30 | try: | 41 | try: |
31 | import threading as _threading | 42 | import threading as _threading |
@@ -228,6 +239,9 @@ later is required to fix a server side protocol bug. | |||
228 | # We'll set to true once we've locked the lock. | 239 | # We'll set to true once we've locked the lock. |
229 | did_lock = False | 240 | did_lock = False |
230 | 241 | ||
242 | if not opt.quiet: | ||
243 | print('Fetching project %s' % project.name) | ||
244 | |||
231 | # Encapsulate everything in a try/except/finally so that: | 245 | # Encapsulate everything in a try/except/finally so that: |
232 | # - We always set err_event in the case of an exception. | 246 | # - We always set err_event in the case of an exception. |
233 | # - We always make sure we call sem.release(). | 247 | # - We always make sure we call sem.release(). |
@@ -274,6 +288,8 @@ later is required to fix a server side protocol bug. | |||
274 | if self.jobs == 1: | 288 | if self.jobs == 1: |
275 | for project in projects: | 289 | for project in projects: |
276 | pm.update() | 290 | pm.update() |
291 | if not opt.quiet: | ||
292 | print('Fetching project %s' % project.name) | ||
277 | if project.Sync_NetworkHalf( | 293 | if project.Sync_NetworkHalf( |
278 | quiet=opt.quiet, | 294 | quiet=opt.quiet, |
279 | current_branch_only=opt.current_branch_only, | 295 | current_branch_only=opt.current_branch_only, |
@@ -372,6 +388,13 @@ later is required to fix a server side protocol bug. | |||
372 | print('\nerror: Exited sync due to gc errors', file=sys.stderr) | 388 | print('\nerror: Exited sync due to gc errors', file=sys.stderr) |
373 | sys.exit(1) | 389 | sys.exit(1) |
374 | 390 | ||
391 | def _ReloadManifest(self, manifest_name=None): | ||
392 | if manifest_name: | ||
393 | # Override calls _Unload already | ||
394 | self.manifest.Override(manifest_name) | ||
395 | else: | ||
396 | self.manifest._Unload() | ||
397 | |||
375 | def UpdateProjectList(self): | 398 | def UpdateProjectList(self): |
376 | new_project_paths = [] | 399 | new_project_paths = [] |
377 | for project in self.GetProjects(None, missing_ok=True): | 400 | for project in self.GetProjects(None, missing_ok=True): |
@@ -406,7 +429,7 @@ later is required to fix a server side protocol bug. | |||
406 | groups = None) | 429 | groups = None) |
407 | 430 | ||
408 | if project.IsDirty(): | 431 | if project.IsDirty(): |
409 | print('error: Cannot remove project "%s": uncommitted changes' | 432 | print('error: Cannot remove project "%s": uncommitted changes ' |
410 | 'are present' % project.relpath, file=sys.stderr) | 433 | 'are present' % project.relpath, file=sys.stderr) |
411 | print(' commit changes, then run sync again', | 434 | print(' commit changes, then run sync again', |
412 | file=sys.stderr) | 435 | file=sys.stderr) |
@@ -464,13 +487,17 @@ later is required to fix a server side protocol bug. | |||
464 | if opt.manifest_name: | 487 | if opt.manifest_name: |
465 | self.manifest.Override(opt.manifest_name) | 488 | self.manifest.Override(opt.manifest_name) |
466 | 489 | ||
490 | manifest_name = opt.manifest_name | ||
491 | |||
467 | if opt.smart_sync or opt.smart_tag: | 492 | if opt.smart_sync or opt.smart_tag: |
468 | if not self.manifest.manifest_server: | 493 | if not self.manifest.manifest_server: |
469 | print('error: cannot smart sync: no manifest server defined in' | 494 | print('error: cannot smart sync: no manifest server defined in ' |
470 | 'manifest', file=sys.stderr) | 495 | 'manifest', file=sys.stderr) |
471 | sys.exit(1) | 496 | sys.exit(1) |
472 | 497 | ||
473 | manifest_server = self.manifest.manifest_server | 498 | manifest_server = self.manifest.manifest_server |
499 | if not opt.quiet: | ||
500 | print('Using manifest server %s' % manifest_server) | ||
474 | 501 | ||
475 | if not '@' in manifest_server: | 502 | if not '@' in manifest_server: |
476 | username = None | 503 | username = None |
@@ -486,7 +513,7 @@ later is required to fix a server side protocol bug. | |||
486 | file=sys.stderr) | 513 | file=sys.stderr) |
487 | else: | 514 | else: |
488 | try: | 515 | try: |
489 | parse_result = urlparse.urlparse(manifest_server) | 516 | parse_result = urllib.parse.urlparse(manifest_server) |
490 | if parse_result.hostname: | 517 | if parse_result.hostname: |
491 | username, _account, password = \ | 518 | username, _account, password = \ |
492 | info.authenticators(parse_result.hostname) | 519 | info.authenticators(parse_result.hostname) |
@@ -504,7 +531,7 @@ later is required to fix a server side protocol bug. | |||
504 | 1) | 531 | 1) |
505 | 532 | ||
506 | try: | 533 | try: |
507 | server = xmlrpclib.Server(manifest_server) | 534 | server = xmlrpc.client.Server(manifest_server) |
508 | if opt.smart_sync: | 535 | if opt.smart_sync: |
509 | p = self.manifest.manifestProject | 536 | p = self.manifest.manifestProject |
510 | b = p.GetBranch(p.CurrentBranch) | 537 | b = p.GetBranch(p.CurrentBranch) |
@@ -513,8 +540,7 @@ later is required to fix a server side protocol bug. | |||
513 | branch = branch[len(R_HEADS):] | 540 | branch = branch[len(R_HEADS):] |
514 | 541 | ||
515 | env = os.environ.copy() | 542 | env = os.environ.copy() |
516 | if (env.has_key('TARGET_PRODUCT') and | 543 | if 'TARGET_PRODUCT' in env and 'TARGET_BUILD_VARIANT' in env: |
517 | env.has_key('TARGET_BUILD_VARIANT')): | ||
518 | target = '%s-%s' % (env['TARGET_PRODUCT'], | 544 | target = '%s-%s' % (env['TARGET_PRODUCT'], |
519 | env['TARGET_BUILD_VARIANT']) | 545 | env['TARGET_BUILD_VARIANT']) |
520 | [success, manifest_str] = server.GetApprovedManifest(branch, target) | 546 | [success, manifest_str] = server.GetApprovedManifest(branch, target) |
@@ -538,15 +564,16 @@ later is required to fix a server side protocol bug. | |||
538 | print('error: cannot write manifest to %s' % manifest_path, | 564 | print('error: cannot write manifest to %s' % manifest_path, |
539 | file=sys.stderr) | 565 | file=sys.stderr) |
540 | sys.exit(1) | 566 | sys.exit(1) |
541 | self.manifest.Override(manifest_name) | 567 | self._ReloadManifest(manifest_name) |
542 | else: | 568 | else: |
543 | print('error: %s' % manifest_str, file=sys.stderr) | 569 | print('error: manifest server RPC call failed: %s' % |
570 | manifest_str, file=sys.stderr) | ||
544 | sys.exit(1) | 571 | sys.exit(1) |
545 | except (socket.error, IOError, xmlrpclib.Fault) as e: | 572 | except (socket.error, IOError, xmlrpc.client.Fault) as e: |
546 | print('error: cannot connect to manifest server %s:\n%s' | 573 | print('error: cannot connect to manifest server %s:\n%s' |
547 | % (self.manifest.manifest_server, e), file=sys.stderr) | 574 | % (self.manifest.manifest_server, e), file=sys.stderr) |
548 | sys.exit(1) | 575 | sys.exit(1) |
549 | except xmlrpclib.ProtocolError as e: | 576 | except xmlrpc.client.ProtocolError as e: |
550 | print('error: cannot connect to manifest server %s:\n%d %s' | 577 | print('error: cannot connect to manifest server %s:\n%d %s' |
551 | % (self.manifest.manifest_server, e.errcode, e.errmsg), | 578 | % (self.manifest.manifest_server, e.errcode, e.errmsg), |
552 | file=sys.stderr) | 579 | file=sys.stderr) |
@@ -571,7 +598,7 @@ later is required to fix a server side protocol bug. | |||
571 | mp.Sync_LocalHalf(syncbuf) | 598 | mp.Sync_LocalHalf(syncbuf) |
572 | if not syncbuf.Finish(): | 599 | if not syncbuf.Finish(): |
573 | sys.exit(1) | 600 | sys.exit(1) |
574 | self.manifest._Unload() | 601 | self._ReloadManifest(manifest_name) |
575 | if opt.jobs is None: | 602 | if opt.jobs is None: |
576 | self.jobs = self.manifest.default.sync_j | 603 | self.jobs = self.manifest.default.sync_j |
577 | all_projects = self.GetProjects(args, | 604 | all_projects = self.GetProjects(args, |
@@ -596,7 +623,7 @@ later is required to fix a server side protocol bug. | |||
596 | # Iteratively fetch missing and/or nested unregistered submodules | 623 | # Iteratively fetch missing and/or nested unregistered submodules |
597 | previously_missing_set = set() | 624 | previously_missing_set = set() |
598 | while True: | 625 | while True: |
599 | self.manifest._Unload() | 626 | self._ReloadManifest(manifest_name) |
600 | all_projects = self.GetProjects(args, | 627 | all_projects = self.GetProjects(args, |
601 | missing_ok=True, | 628 | missing_ok=True, |
602 | submodules_ok=opt.fetch_submodules) | 629 | submodules_ok=opt.fetch_submodules) |
diff --git a/subcmds/upload.py b/subcmds/upload.py index e314032a..8d801e08 100644 --- a/subcmds/upload.py +++ b/subcmds/upload.py | |||
@@ -21,19 +21,26 @@ import sys | |||
21 | from command import InteractiveCommand | 21 | from command import InteractiveCommand |
22 | from editor import Editor | 22 | from editor import Editor |
23 | from error import HookError, UploadError | 23 | from error import HookError, UploadError |
24 | from git_command import GitCommand | ||
24 | from project import RepoHook | 25 | from project import RepoHook |
25 | 26 | ||
27 | from pyversion import is_python3 | ||
28 | if not is_python3(): | ||
29 | # pylint:disable=W0622 | ||
30 | input = raw_input | ||
31 | # pylint:enable=W0622 | ||
32 | |||
26 | UNUSUAL_COMMIT_THRESHOLD = 5 | 33 | UNUSUAL_COMMIT_THRESHOLD = 5 |
27 | 34 | ||
28 | def _ConfirmManyUploads(multiple_branches=False): | 35 | def _ConfirmManyUploads(multiple_branches=False): |
29 | if multiple_branches: | 36 | if multiple_branches: |
30 | print('ATTENTION: One or more branches has an unusually high number' | 37 | print('ATTENTION: One or more branches has an unusually high number ' |
31 | 'of commits.') | 38 | 'of commits.') |
32 | else: | 39 | else: |
33 | print('ATTENTION: You are uploading an unusually high number of commits.') | 40 | print('ATTENTION: You are uploading an unusually high number of commits.') |
34 | print('YOU PROBABLY DO NOT MEAN TO DO THIS. (Did you rebase across' | 41 | print('YOU PROBABLY DO NOT MEAN TO DO THIS. (Did you rebase across ' |
35 | 'branches?)') | 42 | 'branches?)') |
36 | answer = raw_input("If you are sure you intend to do this, type 'yes': ").strip() | 43 | answer = input("If you are sure you intend to do this, type 'yes': ").strip() |
37 | return answer == "yes" | 44 | return answer == "yes" |
38 | 45 | ||
39 | def _die(fmt, *args): | 46 | def _die(fmt, *args): |
@@ -140,6 +147,10 @@ Gerrit Code Review: http://code.google.com/p/gerrit/ | |||
140 | p.add_option('-d', '--draft', | 147 | p.add_option('-d', '--draft', |
141 | action='store_true', dest='draft', default=False, | 148 | action='store_true', dest='draft', default=False, |
142 | help='If specified, upload as a draft.') | 149 | help='If specified, upload as a draft.') |
150 | p.add_option('-D', '--destination', '--dest', | ||
151 | type='string', action='store', dest='dest_branch', | ||
152 | metavar='BRANCH', | ||
153 | help='Submit for review on this target branch.') | ||
143 | 154 | ||
144 | # Options relating to upload hook. Note that verify and no-verify are NOT | 155 | # Options relating to upload hook. Note that verify and no-verify are NOT |
145 | # opposites of each other, which is why they store to different locations. | 156 | # opposites of each other, which is why they store to different locations. |
@@ -179,7 +190,8 @@ Gerrit Code Review: http://code.google.com/p/gerrit/ | |||
179 | date = branch.date | 190 | date = branch.date |
180 | commit_list = branch.commits | 191 | commit_list = branch.commits |
181 | 192 | ||
182 | print('Upload project %s/ to remote branch %s:' % (project.relpath, project.revisionExpr)) | 193 | destination = opt.dest_branch or project.dest_branch or project.revisionExpr |
194 | print('Upload project %s/ to remote branch %s:' % (project.relpath, destination)) | ||
183 | print(' branch %s (%2d commit%s, %s):' % ( | 195 | print(' branch %s (%2d commit%s, %s):' % ( |
184 | name, | 196 | name, |
185 | len(commit_list), | 197 | len(commit_list), |
@@ -213,18 +225,21 @@ Gerrit Code Review: http://code.google.com/p/gerrit/ | |||
213 | 225 | ||
214 | b = {} | 226 | b = {} |
215 | for branch in avail: | 227 | for branch in avail: |
228 | if branch is None: | ||
229 | continue | ||
216 | name = branch.name | 230 | name = branch.name |
217 | date = branch.date | 231 | date = branch.date |
218 | commit_list = branch.commits | 232 | commit_list = branch.commits |
219 | 233 | ||
220 | if b: | 234 | if b: |
221 | script.append('#') | 235 | script.append('#') |
236 | destination = opt.dest_branch or project.dest_branch or project.revisionExpr | ||
222 | script.append('# branch %s (%2d commit%s, %s) to remote branch %s:' % ( | 237 | script.append('# branch %s (%2d commit%s, %s) to remote branch %s:' % ( |
223 | name, | 238 | name, |
224 | len(commit_list), | 239 | len(commit_list), |
225 | len(commit_list) != 1 and 's' or '', | 240 | len(commit_list) != 1 and 's' or '', |
226 | date, | 241 | date, |
227 | project.revisionExpr)) | 242 | destination)) |
228 | for commit in commit_list: | 243 | for commit in commit_list: |
229 | script.append('# %s' % commit) | 244 | script.append('# %s' % commit) |
230 | b[name] = branch | 245 | b[name] = branch |
@@ -330,7 +345,21 @@ Gerrit Code Review: http://code.google.com/p/gerrit/ | |||
330 | key = 'review.%s.uploadtopic' % branch.project.remote.review | 345 | key = 'review.%s.uploadtopic' % branch.project.remote.review |
331 | opt.auto_topic = branch.project.config.GetBoolean(key) | 346 | opt.auto_topic = branch.project.config.GetBoolean(key) |
332 | 347 | ||
333 | branch.UploadForReview(people, auto_topic=opt.auto_topic, draft=opt.draft) | 348 | destination = opt.dest_branch or branch.project.dest_branch |
349 | |||
350 | # Make sure our local branch is not setup to track a different remote branch | ||
351 | merge_branch = self._GetMergeBranch(branch.project) | ||
352 | full_dest = 'refs/heads/%s' % destination | ||
353 | if not opt.dest_branch and merge_branch and merge_branch != full_dest: | ||
354 | print('merge branch %s does not match destination branch %s' | ||
355 | % (merge_branch, full_dest)) | ||
356 | print('skipping upload.') | ||
357 | print('Please use `--destination %s` if this is intentional' | ||
358 | % destination) | ||
359 | branch.uploaded = False | ||
360 | continue | ||
361 | |||
362 | branch.UploadForReview(people, auto_topic=opt.auto_topic, draft=opt.draft, dest_branch=destination) | ||
334 | branch.uploaded = True | 363 | branch.uploaded = True |
335 | except UploadError as e: | 364 | except UploadError as e: |
336 | branch.error = e | 365 | branch.error = e |
@@ -364,6 +393,21 @@ Gerrit Code Review: http://code.google.com/p/gerrit/ | |||
364 | if have_errors: | 393 | if have_errors: |
365 | sys.exit(1) | 394 | sys.exit(1) |
366 | 395 | ||
396 | def _GetMergeBranch(self, project): | ||
397 | p = GitCommand(project, | ||
398 | ['rev-parse', '--abbrev-ref', 'HEAD'], | ||
399 | capture_stdout = True, | ||
400 | capture_stderr = True) | ||
401 | p.Wait() | ||
402 | local_branch = p.stdout.strip() | ||
403 | p = GitCommand(project, | ||
404 | ['config', '--get', 'branch.%s.merge' % local_branch], | ||
405 | capture_stdout = True, | ||
406 | capture_stderr = True) | ||
407 | p.Wait() | ||
408 | merge_branch = p.stdout.strip() | ||
409 | return merge_branch | ||
410 | |||
367 | def Execute(self, opt, args): | 411 | def Execute(self, opt, args): |
368 | project_list = self.GetProjects(args) | 412 | project_list = self.GetProjects(args) |
369 | pending = [] | 413 | pending = [] |