diff options
Diffstat (limited to 'subcmds')
-rw-r--r-- | subcmds/abandon.py | 15 | ||||
-rw-r--r-- | subcmds/branches.py | 3 | ||||
-rw-r--r-- | subcmds/checkout.py | 8 | ||||
-rw-r--r-- | subcmds/cherry_pick.py | 21 | ||||
-rw-r--r-- | subcmds/download.py | 27 | ||||
-rw-r--r-- | subcmds/forall.py | 18 | ||||
-rw-r--r-- | subcmds/grep.py | 24 | ||||
-rw-r--r-- | subcmds/help.py | 35 | ||||
-rw-r--r-- | subcmds/info.py | 195 | ||||
-rw-r--r-- | subcmds/init.py | 79 | ||||
-rw-r--r-- | subcmds/list.py | 3 | ||||
-rw-r--r-- | subcmds/manifest.py | 7 | ||||
-rw-r--r-- | subcmds/overview.py | 10 | ||||
-rw-r--r-- | subcmds/prune.py | 5 | ||||
-rw-r--r-- | subcmds/rebase.py | 14 | ||||
-rw-r--r-- | subcmds/selfupdate.py | 3 | ||||
-rw-r--r-- | subcmds/stage.py | 7 | ||||
-rw-r--r-- | subcmds/start.py | 10 | ||||
-rw-r--r-- | subcmds/status.py | 74 | ||||
-rw-r--r-- | subcmds/sync.py | 323 | ||||
-rw-r--r-- | subcmds/upload.py | 81 | ||||
-rw-r--r-- | subcmds/version.py | 13 |
22 files changed, 664 insertions, 311 deletions
diff --git a/subcmds/abandon.py b/subcmds/abandon.py index e17ab2b6..b94ccdd3 100644 --- a/subcmds/abandon.py +++ b/subcmds/abandon.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import sys | 17 | import sys |
17 | from command import Command | 18 | from command import Command |
18 | from git_command import git | 19 | from git_command import git |
@@ -36,7 +37,7 @@ It is equivalent to "git branch -D <branchname>". | |||
36 | 37 | ||
37 | nb = args[0] | 38 | nb = args[0] |
38 | if not git.check_ref_format('heads/%s' % nb): | 39 | if not git.check_ref_format('heads/%s' % nb): |
39 | print >>sys.stderr, "error: '%s' is not a valid name" % nb | 40 | print("error: '%s' is not a valid name" % nb, file=sys.stderr) |
40 | sys.exit(1) | 41 | sys.exit(1) |
41 | 42 | ||
42 | nb = args[0] | 43 | nb = args[0] |
@@ -58,13 +59,13 @@ It is equivalent to "git branch -D <branchname>". | |||
58 | 59 | ||
59 | if err: | 60 | if err: |
60 | for p in err: | 61 | for p in err: |
61 | print >>sys.stderr,\ | 62 | print("error: %s/: cannot abandon %s" % (p.relpath, nb), |
62 | "error: %s/: cannot abandon %s" \ | 63 | file=sys.stderr) |
63 | % (p.relpath, nb) | ||
64 | sys.exit(1) | 64 | sys.exit(1) |
65 | elif not success: | 65 | elif not success: |
66 | print >>sys.stderr, 'error: no project has branch %s' % nb | 66 | print('error: no project has branch %s' % nb, file=sys.stderr) |
67 | sys.exit(1) | 67 | sys.exit(1) |
68 | else: | 68 | else: |
69 | print >>sys.stderr, 'Abandoned in %d project(s):\n %s' % ( | 69 | print('Abandoned in %d project(s):\n %s' |
70 | len(success), '\n '.join(p.relpath for p in success)) | 70 | % (len(success), '\n '.join(p.relpath for p in success)), |
71 | file=sys.stderr) | ||
diff --git a/subcmds/branches.py b/subcmds/branches.py index a7ba3d6d..06d45abe 100644 --- a/subcmds/branches.py +++ b/subcmds/branches.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import sys | 17 | import sys |
17 | from color import Coloring | 18 | from color import Coloring |
18 | from command import Command | 19 | from command import Command |
@@ -107,7 +108,7 @@ is shown, then the branch appears in all projects. | |||
107 | names.sort() | 108 | names.sort() |
108 | 109 | ||
109 | if not names: | 110 | if not names: |
110 | print >>sys.stderr, ' (no branches)' | 111 | print(' (no branches)', file=sys.stderr) |
111 | return | 112 | return |
112 | 113 | ||
113 | width = 25 | 114 | width = 25 |
diff --git a/subcmds/checkout.py b/subcmds/checkout.py index bfbe9921..cbbca106 100644 --- a/subcmds/checkout.py +++ b/subcmds/checkout.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import sys | 17 | import sys |
17 | from command import Command | 18 | from command import Command |
18 | from progress import Progress | 19 | from progress import Progress |
@@ -55,10 +56,9 @@ The command is equivalent to: | |||
55 | 56 | ||
56 | if err: | 57 | if err: |
57 | for p in err: | 58 | for p in err: |
58 | print >>sys.stderr,\ | 59 | print("error: %s/: cannot checkout %s" % (p.relpath, nb), |
59 | "error: %s/: cannot checkout %s" \ | 60 | file=sys.stderr) |
60 | % (p.relpath, nb) | ||
61 | sys.exit(1) | 61 | sys.exit(1) |
62 | elif not success: | 62 | elif not success: |
63 | print >>sys.stderr, 'error: no project has branch %s' % nb | 63 | print('error: no project has branch %s' % nb, file=sys.stderr) |
64 | sys.exit(1) | 64 | sys.exit(1) |
diff --git a/subcmds/cherry_pick.py b/subcmds/cherry_pick.py index 7a6d4c20..01b97e07 100644 --- a/subcmds/cherry_pick.py +++ b/subcmds/cherry_pick.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import re | 17 | import re |
17 | import sys | 18 | import sys |
18 | from command import Command | 19 | from command import Command |
@@ -46,13 +47,13 @@ change id will be added. | |||
46 | capture_stdout = True, | 47 | capture_stdout = True, |
47 | capture_stderr = True) | 48 | capture_stderr = True) |
48 | if p.Wait() != 0: | 49 | if p.Wait() != 0: |
49 | print >>sys.stderr, p.stderr | 50 | print(p.stderr, file=sys.stderr) |
50 | sys.exit(1) | 51 | sys.exit(1) |
51 | sha1 = p.stdout.strip() | 52 | sha1 = p.stdout.strip() |
52 | 53 | ||
53 | p = GitCommand(None, ['cat-file', 'commit', sha1], capture_stdout=True) | 54 | p = GitCommand(None, ['cat-file', 'commit', sha1], capture_stdout=True) |
54 | if p.Wait() != 0: | 55 | if p.Wait() != 0: |
55 | print >>sys.stderr, "error: Failed to retrieve old commit message" | 56 | print("error: Failed to retrieve old commit message", file=sys.stderr) |
56 | sys.exit(1) | 57 | sys.exit(1) |
57 | old_msg = self._StripHeader(p.stdout) | 58 | old_msg = self._StripHeader(p.stdout) |
58 | 59 | ||
@@ -62,8 +63,8 @@ change id will be added. | |||
62 | capture_stderr = True) | 63 | capture_stderr = True) |
63 | status = p.Wait() | 64 | status = p.Wait() |
64 | 65 | ||
65 | print >>sys.stdout, p.stdout | 66 | print(p.stdout, file=sys.stdout) |
66 | print >>sys.stderr, p.stderr | 67 | print(p.stderr, file=sys.stderr) |
67 | 68 | ||
68 | if status == 0: | 69 | if status == 0: |
69 | # The cherry-pick was applied correctly. We just need to edit the | 70 | # The cherry-pick was applied correctly. We just need to edit the |
@@ -76,16 +77,14 @@ change id will be added. | |||
76 | capture_stderr = True) | 77 | capture_stderr = True) |
77 | p.stdin.write(new_msg) | 78 | p.stdin.write(new_msg) |
78 | if p.Wait() != 0: | 79 | if p.Wait() != 0: |
79 | print >>sys.stderr, "error: Failed to update commit message" | 80 | print("error: Failed to update commit message", file=sys.stderr) |
80 | sys.exit(1) | 81 | sys.exit(1) |
81 | 82 | ||
82 | else: | 83 | else: |
83 | print >>sys.stderr, """\ | 84 | print('NOTE: When committing (please see above) and editing the commit' |
84 | NOTE: When committing (please see above) and editing the commit message, | 85 | 'message, please remove the old Change-Id-line and add:') |
85 | please remove the old Change-Id-line and add: | 86 | print(self._GetReference(sha1), file=sys.stderr) |
86 | """ | 87 | print(file=sys.stderr) |
87 | print >>sys.stderr, self._GetReference(sha1) | ||
88 | print >>sys.stderr | ||
89 | 88 | ||
90 | def _IsChangeId(self, line): | 89 | def _IsChangeId(self, line): |
91 | return CHANGE_ID_RE.match(line) | 90 | return CHANGE_ID_RE.match(line) |
diff --git a/subcmds/download.py b/subcmds/download.py index 0abe90d0..471e88b5 100644 --- a/subcmds/download.py +++ b/subcmds/download.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import re | 17 | import re |
17 | import sys | 18 | import sys |
18 | 19 | ||
@@ -32,13 +33,13 @@ makes it available in your project's local working directory. | |||
32 | """ | 33 | """ |
33 | 34 | ||
34 | def _Options(self, p): | 35 | def _Options(self, p): |
35 | p.add_option('-c','--cherry-pick', | 36 | p.add_option('-c', '--cherry-pick', |
36 | dest='cherrypick', action='store_true', | 37 | dest='cherrypick', action='store_true', |
37 | help="cherry-pick instead of checkout") | 38 | help="cherry-pick instead of checkout") |
38 | p.add_option('-r','--revert', | 39 | p.add_option('-r', '--revert', |
39 | dest='revert', action='store_true', | 40 | dest='revert', action='store_true', |
40 | help="revert instead of checkout") | 41 | help="revert instead of checkout") |
41 | p.add_option('-f','--ff-only', | 42 | p.add_option('-f', '--ff-only', |
42 | dest='ffonly', action='store_true', | 43 | dest='ffonly', action='store_true', |
43 | help="force fast-forward merge") | 44 | help="force fast-forward merge") |
44 | 45 | ||
@@ -68,23 +69,23 @@ makes it available in your project's local working directory. | |||
68 | for project, change_id, ps_id in self._ParseChangeIds(args): | 69 | for project, change_id, ps_id in self._ParseChangeIds(args): |
69 | dl = project.DownloadPatchSet(change_id, ps_id) | 70 | dl = project.DownloadPatchSet(change_id, ps_id) |
70 | if not dl: | 71 | if not dl: |
71 | print >>sys.stderr, \ | 72 | print('[%s] change %d/%d not found' |
72 | '[%s] change %d/%d not found' \ | 73 | % (project.name, change_id, ps_id), |
73 | % (project.name, change_id, ps_id) | 74 | file=sys.stderr) |
74 | sys.exit(1) | 75 | sys.exit(1) |
75 | 76 | ||
76 | if not opt.revert and not dl.commits: | 77 | if not opt.revert and not dl.commits: |
77 | print >>sys.stderr, \ | 78 | print('[%s] change %d/%d has already been merged' |
78 | '[%s] change %d/%d has already been merged' \ | 79 | % (project.name, change_id, ps_id), |
79 | % (project.name, change_id, ps_id) | 80 | file=sys.stderr) |
80 | continue | 81 | continue |
81 | 82 | ||
82 | if len(dl.commits) > 1: | 83 | if len(dl.commits) > 1: |
83 | print >>sys.stderr, \ | 84 | print('[%s] %d/%d depends on %d unmerged changes:' \ |
84 | '[%s] %d/%d depends on %d unmerged changes:' \ | 85 | % (project.name, change_id, ps_id, len(dl.commits)), |
85 | % (project.name, change_id, ps_id, len(dl.commits)) | 86 | file=sys.stderr) |
86 | for c in dl.commits: | 87 | for c in dl.commits: |
87 | print >>sys.stderr, ' %s' % (c) | 88 | print(' %s' % (c), file=sys.stderr) |
88 | if opt.cherrypick: | 89 | if opt.cherrypick: |
89 | project._CherryPick(dl.commit) | 90 | project._CherryPick(dl.commit) |
90 | elif opt.revert: | 91 | elif opt.revert: |
diff --git a/subcmds/forall.py b/subcmds/forall.py index b633b7d4..4c1c9ff8 100644 --- a/subcmds/forall.py +++ b/subcmds/forall.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import fcntl | 17 | import fcntl |
17 | import re | 18 | import re |
18 | import os | 19 | import os |
@@ -92,6 +93,9 @@ following <command>. | |||
92 | 93 | ||
93 | Unless -p is used, stdin, stdout, stderr are inherited from the | 94 | Unless -p is used, stdin, stdout, stderr are inherited from the |
94 | terminal and are not redirected. | 95 | terminal and are not redirected. |
96 | |||
97 | If -e is used, when a command exits unsuccessfully, '%prog' will abort | ||
98 | without iterating through the remaining projects. | ||
95 | """ | 99 | """ |
96 | 100 | ||
97 | def _Options(self, p): | 101 | def _Options(self, p): |
@@ -104,6 +108,9 @@ terminal and are not redirected. | |||
104 | dest='command', | 108 | dest='command', |
105 | action='callback', | 109 | action='callback', |
106 | callback=cmd) | 110 | callback=cmd) |
111 | p.add_option('-e', '--abort-on-errors', | ||
112 | dest='abort_on_errors', action='store_true', | ||
113 | help='Abort if a command exits unsuccessfully') | ||
107 | 114 | ||
108 | g = p.add_option_group('Output') | 115 | g = p.add_option_group('Output') |
109 | g.add_option('-p', | 116 | g.add_option('-p', |
@@ -183,7 +190,7 @@ terminal and are not redirected. | |||
183 | if not os.path.exists(cwd): | 190 | if not os.path.exists(cwd): |
184 | if (opt.project_header and opt.verbose) \ | 191 | if (opt.project_header and opt.verbose) \ |
185 | or not opt.project_header: | 192 | or not opt.project_header: |
186 | print >>sys.stderr, 'skipping %s/' % project.relpath | 193 | print('skipping %s/' % project.relpath, file=sys.stderr) |
187 | continue | 194 | continue |
188 | 195 | ||
189 | if opt.project_header: | 196 | if opt.project_header: |
@@ -254,7 +261,12 @@ terminal and are not redirected. | |||
254 | s.dest.flush() | 261 | s.dest.flush() |
255 | 262 | ||
256 | r = p.wait() | 263 | r = p.wait() |
257 | if r != 0 and r != rc: | 264 | if r != 0: |
258 | rc = r | 265 | if r != rc: |
266 | rc = r | ||
267 | if opt.abort_on_errors: | ||
268 | print("error: %s: Aborting due to previous error" % project.relpath, | ||
269 | file=sys.stderr) | ||
270 | sys.exit(r) | ||
259 | if rc != 0: | 271 | if rc != 0: |
260 | sys.exit(rc) | 272 | sys.exit(rc) |
diff --git a/subcmds/grep.py b/subcmds/grep.py index 0dc8f9f6..dd391cfa 100644 --- a/subcmds/grep.py +++ b/subcmds/grep.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import sys | 17 | import sys |
17 | from color import Coloring | 18 | from color import Coloring |
18 | from command import PagedCommand | 19 | from command import PagedCommand |
@@ -51,7 +52,7 @@ Examples | |||
51 | 52 | ||
52 | Look for a line that has '#define' and either 'MAX_PATH or 'PATH_MAX': | 53 | Look for a line that has '#define' and either 'MAX_PATH or 'PATH_MAX': |
53 | 54 | ||
54 | repo grep -e '#define' --and -\( -e MAX_PATH -e PATH_MAX \) | 55 | repo grep -e '#define' --and -\\( -e MAX_PATH -e PATH_MAX \\) |
55 | 56 | ||
56 | Look for a line that has 'NODE' or 'Unexpected' in files that | 57 | Look for a line that has 'NODE' or 'Unexpected' in files that |
57 | contain a line that matches both expressions: | 58 | contain a line that matches both expressions: |
@@ -84,7 +85,7 @@ contain a line that matches both expressions: | |||
84 | g.add_option('--cached', | 85 | g.add_option('--cached', |
85 | action='callback', callback=carry, | 86 | action='callback', callback=carry, |
86 | help='Search the index, instead of the work tree') | 87 | help='Search the index, instead of the work tree') |
87 | g.add_option('-r','--revision', | 88 | g.add_option('-r', '--revision', |
88 | dest='revision', action='append', metavar='TREEish', | 89 | dest='revision', action='append', metavar='TREEish', |
89 | help='Search TREEish, instead of the work tree') | 90 | help='Search TREEish, instead of the work tree') |
90 | 91 | ||
@@ -96,7 +97,7 @@ contain a line that matches both expressions: | |||
96 | g.add_option('-i', '--ignore-case', | 97 | g.add_option('-i', '--ignore-case', |
97 | action='callback', callback=carry, | 98 | action='callback', callback=carry, |
98 | help='Ignore case differences') | 99 | help='Ignore case differences') |
99 | g.add_option('-a','--text', | 100 | g.add_option('-a', '--text', |
100 | action='callback', callback=carry, | 101 | action='callback', callback=carry, |
101 | help="Process binary files as if they were text") | 102 | help="Process binary files as if they were text") |
102 | g.add_option('-I', | 103 | g.add_option('-I', |
@@ -125,7 +126,7 @@ contain a line that matches both expressions: | |||
125 | g.add_option('--and', '--or', '--not', | 126 | g.add_option('--and', '--or', '--not', |
126 | action='callback', callback=carry, | 127 | action='callback', callback=carry, |
127 | help='Boolean operators to combine patterns') | 128 | help='Boolean operators to combine patterns') |
128 | g.add_option('-(','-)', | 129 | g.add_option('-(', '-)', |
129 | action='callback', callback=carry, | 130 | action='callback', callback=carry, |
130 | help='Boolean operator grouping') | 131 | help='Boolean operator grouping') |
131 | 132 | ||
@@ -145,10 +146,10 @@ contain a line that matches both expressions: | |||
145 | action='callback', callback=carry, | 146 | action='callback', callback=carry, |
146 | metavar='CONTEXT', type='str', | 147 | metavar='CONTEXT', type='str', |
147 | help='Show CONTEXT lines after match') | 148 | help='Show CONTEXT lines after match') |
148 | g.add_option('-l','--name-only','--files-with-matches', | 149 | g.add_option('-l', '--name-only', '--files-with-matches', |
149 | action='callback', callback=carry, | 150 | action='callback', callback=carry, |
150 | help='Show only file names containing matching lines') | 151 | help='Show only file names containing matching lines') |
151 | g.add_option('-L','--files-without-match', | 152 | g.add_option('-L', '--files-without-match', |
152 | action='callback', callback=carry, | 153 | action='callback', callback=carry, |
153 | help='Show only file names not containing matching lines') | 154 | help='Show only file names not containing matching lines') |
154 | 155 | ||
@@ -157,9 +158,9 @@ contain a line that matches both expressions: | |||
157 | out = GrepColoring(self.manifest.manifestProject.config) | 158 | out = GrepColoring(self.manifest.manifestProject.config) |
158 | 159 | ||
159 | cmd_argv = ['grep'] | 160 | cmd_argv = ['grep'] |
160 | if out.is_on and git_require((1,6,3)): | 161 | if out.is_on and git_require((1, 6, 3)): |
161 | cmd_argv.append('--color') | 162 | cmd_argv.append('--color') |
162 | cmd_argv.extend(getattr(opt,'cmd_argv',[])) | 163 | cmd_argv.extend(getattr(opt, 'cmd_argv', [])) |
163 | 164 | ||
164 | if '-e' not in cmd_argv: | 165 | if '-e' not in cmd_argv: |
165 | if not args: | 166 | if not args: |
@@ -178,8 +179,7 @@ contain a line that matches both expressions: | |||
178 | have_rev = False | 179 | have_rev = False |
179 | if opt.revision: | 180 | if opt.revision: |
180 | if '--cached' in cmd_argv: | 181 | if '--cached' in cmd_argv: |
181 | print >>sys.stderr,\ | 182 | print('fatal: cannot combine --cached and --revision', file=sys.stderr) |
182 | 'fatal: cannot combine --cached and --revision' | ||
183 | sys.exit(1) | 183 | sys.exit(1) |
184 | have_rev = True | 184 | have_rev = True |
185 | cmd_argv.extend(opt.revision) | 185 | cmd_argv.extend(opt.revision) |
@@ -230,13 +230,13 @@ contain a line that matches both expressions: | |||
230 | out.nl() | 230 | out.nl() |
231 | else: | 231 | else: |
232 | for line in r: | 232 | for line in r: |
233 | print line | 233 | print(line) |
234 | 234 | ||
235 | if have_match: | 235 | if have_match: |
236 | sys.exit(0) | 236 | sys.exit(0) |
237 | elif have_rev and bad_rev: | 237 | elif have_rev and bad_rev: |
238 | for r in opt.revision: | 238 | for r in opt.revision: |
239 | print >>sys.stderr, "error: can't search revision %s" % r | 239 | print("error: can't search revision %s" % r, file=sys.stderr) |
240 | sys.exit(1) | 240 | sys.exit(1) |
241 | else: | 241 | else: |
242 | sys.exit(1) | 242 | sys.exit(1) |
diff --git a/subcmds/help.py b/subcmds/help.py index 375d04d2..15aab7f9 100644 --- a/subcmds/help.py +++ b/subcmds/help.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import re | 17 | import re |
17 | import sys | 18 | import sys |
18 | from formatter import AbstractFormatter, DumbWriter | 19 | from formatter import AbstractFormatter, DumbWriter |
@@ -31,10 +32,8 @@ Displays detailed usage information about a command. | |||
31 | """ | 32 | """ |
32 | 33 | ||
33 | def _PrintAllCommands(self): | 34 | def _PrintAllCommands(self): |
34 | print 'usage: repo COMMAND [ARGS]' | 35 | print('usage: repo COMMAND [ARGS]') |
35 | print """ | 36 | print('The complete list of recognized repo commands are:') |
36 | The complete list of recognized repo commands are: | ||
37 | """ | ||
38 | commandNames = self.commands.keys() | 37 | commandNames = self.commands.keys() |
39 | commandNames.sort() | 38 | commandNames.sort() |
40 | 39 | ||
@@ -49,17 +48,14 @@ The complete list of recognized repo commands are: | |||
49 | summary = command.helpSummary.strip() | 48 | summary = command.helpSummary.strip() |
50 | except AttributeError: | 49 | except AttributeError: |
51 | summary = '' | 50 | summary = '' |
52 | print fmt % (name, summary) | 51 | print(fmt % (name, summary)) |
53 | print """ | 52 | print("See 'repo help <command>' for more information on a" |
54 | See 'repo help <command>' for more information on a specific command. | 53 | 'specific command.') |
55 | """ | ||
56 | 54 | ||
57 | def _PrintCommonCommands(self): | 55 | def _PrintCommonCommands(self): |
58 | print 'usage: repo COMMAND [ARGS]' | 56 | print('usage: repo COMMAND [ARGS]') |
59 | print """ | 57 | print('The most commonly used repo commands are:') |
60 | The most commonly used repo commands are: | 58 | commandNames = [name |
61 | """ | ||
62 | commandNames = [name | ||
63 | for name in self.commands.keys() | 59 | for name in self.commands.keys() |
64 | if self.commands[name].common] | 60 | if self.commands[name].common] |
65 | commandNames.sort() | 61 | commandNames.sort() |
@@ -75,11 +71,10 @@ The most commonly used repo commands are: | |||
75 | summary = command.helpSummary.strip() | 71 | summary = command.helpSummary.strip() |
76 | except AttributeError: | 72 | except AttributeError: |
77 | summary = '' | 73 | summary = '' |
78 | print fmt % (name, summary) | 74 | print(fmt % (name, summary)) |
79 | print """ | 75 | print( |
80 | See 'repo help <command>' for more information on a specific command. | 76 | "See 'repo help <command>' for more information on a specific command.\n" |
81 | See 'repo help --all' for a complete list of recognized commands. | 77 | "See 'repo help --all' for a complete list of recognized commands.") |
82 | """ | ||
83 | 78 | ||
84 | def _PrintCommandHelp(self, cmd): | 79 | def _PrintCommandHelp(self, cmd): |
85 | class _Out(Coloring): | 80 | class _Out(Coloring): |
@@ -131,7 +126,7 @@ See 'repo help --all' for a complete list of recognized commands. | |||
131 | 126 | ||
132 | p('%s', title) | 127 | p('%s', title) |
133 | self.nl() | 128 | self.nl() |
134 | p('%s', ''.ljust(len(title),section_type[0])) | 129 | p('%s', ''.ljust(len(title), section_type[0])) |
135 | self.nl() | 130 | self.nl() |
136 | continue | 131 | continue |
137 | 132 | ||
@@ -162,7 +157,7 @@ See 'repo help --all' for a complete list of recognized commands. | |||
162 | try: | 157 | try: |
163 | cmd = self.commands[name] | 158 | cmd = self.commands[name] |
164 | except KeyError: | 159 | except KeyError: |
165 | print >>sys.stderr, "repo: '%s' is not a repo command." % name | 160 | print("repo: '%s' is not a repo command." % name, file=sys.stderr) |
166 | sys.exit(1) | 161 | sys.exit(1) |
167 | 162 | ||
168 | cmd.manifest = self.manifest | 163 | cmd.manifest = self.manifest |
diff --git a/subcmds/info.py b/subcmds/info.py new file mode 100644 index 00000000..a6eba889 --- /dev/null +++ b/subcmds/info.py | |||
@@ -0,0 +1,195 @@ | |||
1 | # | ||
2 | # Copyright (C) 2012 The Android Open Source Project | ||
3 | # | ||
4 | # Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | # you may not use this file except in compliance with the License. | ||
6 | # You may obtain a copy of the License at | ||
7 | # | ||
8 | # http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | # | ||
10 | # Unless required by applicable law or agreed to in writing, software | ||
11 | # distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | # See the License for the specific language governing permissions and | ||
14 | # limitations under the License. | ||
15 | |||
16 | from command import PagedCommand | ||
17 | from color import Coloring | ||
18 | from error import NoSuchProjectError | ||
19 | from git_refs import R_M | ||
20 | |||
21 | class _Coloring(Coloring): | ||
22 | def __init__(self, config): | ||
23 | Coloring.__init__(self, config, "status") | ||
24 | |||
25 | class Info(PagedCommand): | ||
26 | common = True | ||
27 | helpSummary = "Get info on the manifest branch, current branch or unmerged branches" | ||
28 | helpUsage = "%prog [-dl] [-o [-b]] [<project>...]" | ||
29 | |||
30 | def _Options(self, p, show_smart=True): | ||
31 | p.add_option('-d', '--diff', | ||
32 | dest='all', action='store_true', | ||
33 | help="show full info and commit diff including remote branches") | ||
34 | p.add_option('-o', '--overview', | ||
35 | dest='overview', action='store_true', | ||
36 | help='show overview of all local commits') | ||
37 | p.add_option('-b', '--current-branch', | ||
38 | dest="current_branch", action="store_true", | ||
39 | help="consider only checked out branches") | ||
40 | p.add_option('-l', '--local-only', | ||
41 | dest="local", action="store_true", | ||
42 | help="Disable all remote operations") | ||
43 | |||
44 | |||
45 | def Execute(self, opt, args): | ||
46 | self.out = _Coloring(self.manifest.globalConfig) | ||
47 | self.heading = self.out.printer('heading', attr = 'bold') | ||
48 | self.headtext = self.out.printer('headtext', fg = 'yellow') | ||
49 | self.redtext = self.out.printer('redtext', fg = 'red') | ||
50 | self.sha = self.out.printer("sha", fg = 'yellow') | ||
51 | self.text = self.out.printer('text') | ||
52 | self.dimtext = self.out.printer('dimtext', attr = 'dim') | ||
53 | |||
54 | self.opt = opt | ||
55 | |||
56 | mergeBranch = self.manifest.manifestProject.config.GetBranch("default").merge | ||
57 | |||
58 | self.heading("Manifest branch: ") | ||
59 | self.headtext(self.manifest.default.revisionExpr) | ||
60 | self.out.nl() | ||
61 | self.heading("Manifest merge branch: ") | ||
62 | self.headtext(mergeBranch) | ||
63 | self.out.nl() | ||
64 | |||
65 | self.printSeparator() | ||
66 | |||
67 | if not opt.overview: | ||
68 | self.printDiffInfo(args) | ||
69 | else: | ||
70 | self.printCommitOverview(args) | ||
71 | |||
72 | def printSeparator(self): | ||
73 | self.text("----------------------------") | ||
74 | self.out.nl() | ||
75 | |||
76 | def printDiffInfo(self, args): | ||
77 | try: | ||
78 | projs = self.GetProjects(args) | ||
79 | except NoSuchProjectError: | ||
80 | return | ||
81 | |||
82 | for p in projs: | ||
83 | self.heading("Project: ") | ||
84 | self.headtext(p.name) | ||
85 | self.out.nl() | ||
86 | |||
87 | self.heading("Mount path: ") | ||
88 | self.headtext(p.worktree) | ||
89 | self.out.nl() | ||
90 | |||
91 | self.heading("Current revision: ") | ||
92 | self.headtext(p.revisionExpr) | ||
93 | self.out.nl() | ||
94 | |||
95 | localBranches = p.GetBranches().keys() | ||
96 | self.heading("Local Branches: ") | ||
97 | self.redtext(str(len(localBranches))) | ||
98 | if len(localBranches) > 0: | ||
99 | self.text(" [") | ||
100 | self.text(", ".join(localBranches)) | ||
101 | self.text("]") | ||
102 | self.out.nl() | ||
103 | |||
104 | if self.opt.all: | ||
105 | self.findRemoteLocalDiff(p) | ||
106 | |||
107 | self.printSeparator() | ||
108 | |||
109 | def findRemoteLocalDiff(self, project): | ||
110 | #Fetch all the latest commits | ||
111 | if not self.opt.local: | ||
112 | project.Sync_NetworkHalf(quiet=True, current_branch_only=True) | ||
113 | |||
114 | logTarget = R_M + self.manifest.manifestProject.config.GetBranch("default").merge | ||
115 | |||
116 | bareTmp = project.bare_git._bare | ||
117 | project.bare_git._bare = False | ||
118 | localCommits = project.bare_git.rev_list( | ||
119 | '--abbrev=8', | ||
120 | '--abbrev-commit', | ||
121 | '--pretty=oneline', | ||
122 | logTarget + "..", | ||
123 | '--') | ||
124 | |||
125 | originCommits = project.bare_git.rev_list( | ||
126 | '--abbrev=8', | ||
127 | '--abbrev-commit', | ||
128 | '--pretty=oneline', | ||
129 | ".." + logTarget, | ||
130 | '--') | ||
131 | project.bare_git._bare = bareTmp | ||
132 | |||
133 | self.heading("Local Commits: ") | ||
134 | self.redtext(str(len(localCommits))) | ||
135 | self.dimtext(" (on current branch)") | ||
136 | self.out.nl() | ||
137 | |||
138 | for c in localCommits: | ||
139 | split = c.split() | ||
140 | self.sha(split[0] + " ") | ||
141 | self.text(" ".join(split[1:])) | ||
142 | self.out.nl() | ||
143 | |||
144 | self.printSeparator() | ||
145 | |||
146 | self.heading("Remote Commits: ") | ||
147 | self.redtext(str(len(originCommits))) | ||
148 | self.out.nl() | ||
149 | |||
150 | for c in originCommits: | ||
151 | split = c.split() | ||
152 | self.sha(split[0] + " ") | ||
153 | self.text(" ".join(split[1:])) | ||
154 | self.out.nl() | ||
155 | |||
156 | def printCommitOverview(self, args): | ||
157 | all_branches = [] | ||
158 | for project in self.GetProjects(args): | ||
159 | br = [project.GetUploadableBranch(x) | ||
160 | for x in project.GetBranches().keys()] | ||
161 | br = [x for x in br if x] | ||
162 | if self.opt.current_branch: | ||
163 | br = [x for x in br if x.name == project.CurrentBranch] | ||
164 | all_branches.extend(br) | ||
165 | |||
166 | if not all_branches: | ||
167 | return | ||
168 | |||
169 | self.out.nl() | ||
170 | self.heading('Projects Overview') | ||
171 | project = None | ||
172 | |||
173 | for branch in all_branches: | ||
174 | if project != branch.project: | ||
175 | project = branch.project | ||
176 | self.out.nl() | ||
177 | self.headtext(project.relpath) | ||
178 | self.out.nl() | ||
179 | |||
180 | commits = branch.commits | ||
181 | date = branch.date | ||
182 | self.text('%s %-33s (%2d commit%s, %s)' % ( | ||
183 | branch.name == project.CurrentBranch and '*' or ' ', | ||
184 | branch.name, | ||
185 | len(commits), | ||
186 | len(commits) != 1 and 's' or '', | ||
187 | date)) | ||
188 | self.out.nl() | ||
189 | |||
190 | for commit in commits: | ||
191 | split = commit.split() | ||
192 | self.text('{0:38}{1} '.format('','-')) | ||
193 | self.sha(split[0] + " ") | ||
194 | self.text(" ".join(split[1:])) | ||
195 | self.out.nl() | ||
diff --git a/subcmds/init.py b/subcmds/init.py index b6b98076..11312601 100644 --- a/subcmds/init.py +++ b/subcmds/init.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import os | 17 | import os |
17 | import platform | 18 | import platform |
18 | import re | 19 | import re |
@@ -117,18 +118,22 @@ to update the working directory files. | |||
117 | dest='config_name', action="store_true", default=False, | 118 | dest='config_name', action="store_true", default=False, |
118 | help='Always prompt for name/e-mail') | 119 | help='Always prompt for name/e-mail') |
119 | 120 | ||
121 | def _RegisteredEnvironmentOptions(self): | ||
122 | return {'REPO_MANIFEST_URL': 'manifest_url', | ||
123 | 'REPO_MIRROR_LOCATION': 'reference'} | ||
124 | |||
120 | def _SyncManifest(self, opt): | 125 | def _SyncManifest(self, opt): |
121 | m = self.manifest.manifestProject | 126 | m = self.manifest.manifestProject |
122 | is_new = not m.Exists | 127 | is_new = not m.Exists |
123 | 128 | ||
124 | if is_new: | 129 | if is_new: |
125 | if not opt.manifest_url: | 130 | if not opt.manifest_url: |
126 | print >>sys.stderr, 'fatal: manifest url (-u) is required.' | 131 | print('fatal: manifest url (-u) is required.', file=sys.stderr) |
127 | sys.exit(1) | 132 | sys.exit(1) |
128 | 133 | ||
129 | if not opt.quiet: | 134 | if not opt.quiet: |
130 | print >>sys.stderr, 'Get %s' \ | 135 | print('Get %s' % GitConfig.ForUser().UrlInsteadOf(opt.manifest_url), |
131 | % GitConfig.ForUser().UrlInsteadOf(opt.manifest_url) | 136 | file=sys.stderr) |
132 | m._InitGitDir() | 137 | m._InitGitDir() |
133 | 138 | ||
134 | if opt.manifest_branch: | 139 | if opt.manifest_branch: |
@@ -147,7 +152,7 @@ to update the working directory files. | |||
147 | r.ResetFetch() | 152 | r.ResetFetch() |
148 | r.Save() | 153 | r.Save() |
149 | 154 | ||
150 | groups = re.split('[,\s]+', opt.groups) | 155 | groups = re.split(r'[,\s]+', opt.groups) |
151 | all_platforms = ['linux', 'darwin'] | 156 | all_platforms = ['linux', 'darwin'] |
152 | platformize = lambda x: 'platform-' + x | 157 | platformize = lambda x: 'platform-' + x |
153 | if opt.platform == 'auto': | 158 | if opt.platform == 'auto': |
@@ -159,7 +164,7 @@ to update the working directory files. | |||
159 | elif opt.platform in all_platforms: | 164 | elif opt.platform in all_platforms: |
160 | groups.extend(platformize(opt.platform)) | 165 | groups.extend(platformize(opt.platform)) |
161 | elif opt.platform != 'none': | 166 | elif opt.platform != 'none': |
162 | print >>sys.stderr, 'fatal: invalid platform flag' | 167 | print('fatal: invalid platform flag', file=sys.stderr) |
163 | sys.exit(1) | 168 | sys.exit(1) |
164 | 169 | ||
165 | groups = [x for x in groups if x] | 170 | groups = [x for x in groups if x] |
@@ -175,12 +180,15 @@ to update the working directory files. | |||
175 | if is_new: | 180 | if is_new: |
176 | m.config.SetString('repo.mirror', 'true') | 181 | m.config.SetString('repo.mirror', 'true') |
177 | else: | 182 | else: |
178 | print >>sys.stderr, 'fatal: --mirror not supported on existing client' | 183 | print('fatal: --mirror is only supported when initializing a new ' |
184 | 'workspace.', file=sys.stderr) | ||
185 | print('Either delete the .repo folder in this workspace, or initialize ' | ||
186 | 'in another location.', file=sys.stderr) | ||
179 | sys.exit(1) | 187 | sys.exit(1) |
180 | 188 | ||
181 | if not m.Sync_NetworkHalf(is_new=is_new): | 189 | if not m.Sync_NetworkHalf(is_new=is_new): |
182 | r = m.GetRemote(m.remote.name) | 190 | r = m.GetRemote(m.remote.name) |
183 | print >>sys.stderr, 'fatal: cannot obtain manifest %s' % r.url | 191 | print('fatal: cannot obtain manifest %s' % r.url, file=sys.stderr) |
184 | 192 | ||
185 | # Better delete the manifest git dir if we created it; otherwise next | 193 | # Better delete the manifest git dir if we created it; otherwise next |
186 | # time (when user fixes problems) we won't go through the "is_new" logic. | 194 | # time (when user fixes problems) we won't go through the "is_new" logic. |
@@ -197,19 +205,19 @@ to update the working directory files. | |||
197 | 205 | ||
198 | if is_new or m.CurrentBranch is None: | 206 | if is_new or m.CurrentBranch is None: |
199 | if not m.StartBranch('default'): | 207 | if not m.StartBranch('default'): |
200 | print >>sys.stderr, 'fatal: cannot create default in manifest' | 208 | print('fatal: cannot create default in manifest', file=sys.stderr) |
201 | sys.exit(1) | 209 | sys.exit(1) |
202 | 210 | ||
203 | def _LinkManifest(self, name): | 211 | def _LinkManifest(self, name): |
204 | if not name: | 212 | if not name: |
205 | print >>sys.stderr, 'fatal: manifest name (-m) is required.' | 213 | print('fatal: manifest name (-m) is required.', file=sys.stderr) |
206 | sys.exit(1) | 214 | sys.exit(1) |
207 | 215 | ||
208 | try: | 216 | try: |
209 | self.manifest.Link(name) | 217 | self.manifest.Link(name) |
210 | except ManifestParseError as e: | 218 | except ManifestParseError as e: |
211 | print >>sys.stderr, "fatal: manifest '%s' not available" % name | 219 | print("fatal: manifest '%s' not available" % name, file=sys.stderr) |
212 | print >>sys.stderr, 'fatal: %s' % str(e) | 220 | print('fatal: %s' % str(e), file=sys.stderr) |
213 | sys.exit(1) | 221 | sys.exit(1) |
214 | 222 | ||
215 | def _Prompt(self, prompt, value): | 223 | def _Prompt(self, prompt, value): |
@@ -231,24 +239,24 @@ to update the working directory files. | |||
231 | mp.config.SetString('user.name', gc.GetString('user.name')) | 239 | mp.config.SetString('user.name', gc.GetString('user.name')) |
232 | mp.config.SetString('user.email', gc.GetString('user.email')) | 240 | mp.config.SetString('user.email', gc.GetString('user.email')) |
233 | 241 | ||
234 | print '' | 242 | print() |
235 | print 'Your identity is: %s <%s>' % (mp.config.GetString('user.name'), | 243 | print('Your identity is: %s <%s>' % (mp.config.GetString('user.name'), |
236 | mp.config.GetString('user.email')) | 244 | mp.config.GetString('user.email'))) |
237 | print 'If you want to change this, please re-run \'repo init\' with --config-name' | 245 | print('If you want to change this, please re-run \'repo init\' with --config-name') |
238 | return False | 246 | return False |
239 | 247 | ||
240 | def _ConfigureUser(self): | 248 | def _ConfigureUser(self): |
241 | mp = self.manifest.manifestProject | 249 | mp = self.manifest.manifestProject |
242 | 250 | ||
243 | while True: | 251 | while True: |
244 | print '' | 252 | print() |
245 | name = self._Prompt('Your Name', mp.UserName) | 253 | name = self._Prompt('Your Name', mp.UserName) |
246 | email = self._Prompt('Your Email', mp.UserEmail) | 254 | email = self._Prompt('Your Email', mp.UserEmail) |
247 | 255 | ||
248 | print '' | 256 | print() |
249 | print 'Your identity is: %s <%s>' % (name, email) | 257 | print('Your identity is: %s <%s>' % (name, email)) |
250 | sys.stdout.write('is this correct [y/N]? ') | 258 | sys.stdout.write('is this correct [y/N]? ') |
251 | a = sys.stdin.readline().strip() | 259 | a = sys.stdin.readline().strip().lower() |
252 | if a in ('yes', 'y', 't', 'true'): | 260 | if a in ('yes', 'y', 't', 'true'): |
253 | break | 261 | break |
254 | 262 | ||
@@ -274,17 +282,17 @@ to update the working directory files. | |||
274 | self._on = True | 282 | self._on = True |
275 | out = _Test() | 283 | out = _Test() |
276 | 284 | ||
277 | print '' | 285 | print() |
278 | print "Testing colorized output (for 'repo diff', 'repo status'):" | 286 | print("Testing colorized output (for 'repo diff', 'repo status'):") |
279 | 287 | ||
280 | for c in ['black','red','green','yellow','blue','magenta','cyan']: | 288 | for c in ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan']: |
281 | out.write(' ') | 289 | out.write(' ') |
282 | out.printer(fg=c)(' %-6s ', c) | 290 | out.printer(fg=c)(' %-6s ', c) |
283 | out.write(' ') | 291 | out.write(' ') |
284 | out.printer(fg='white', bg='black')(' %s ' % 'white') | 292 | out.printer(fg='white', bg='black')(' %s ' % 'white') |
285 | out.nl() | 293 | out.nl() |
286 | 294 | ||
287 | for c in ['bold','dim','ul','reverse']: | 295 | for c in ['bold', 'dim', 'ul', 'reverse']: |
288 | out.write(' ') | 296 | out.write(' ') |
289 | out.printer(fg='black', attr=c)(' %-6s ', c) | 297 | out.printer(fg='black', attr=c)(' %-6s ', c) |
290 | out.nl() | 298 | out.nl() |
@@ -313,6 +321,23 @@ to update the working directory files. | |||
313 | # We store the depth in the main manifest project. | 321 | # We store the depth in the main manifest project. |
314 | self.manifest.manifestProject.config.SetString('repo.depth', depth) | 322 | self.manifest.manifestProject.config.SetString('repo.depth', depth) |
315 | 323 | ||
324 | def _DisplayResult(self): | ||
325 | if self.manifest.IsMirror: | ||
326 | init_type = 'mirror ' | ||
327 | else: | ||
328 | init_type = '' | ||
329 | |||
330 | print() | ||
331 | print('repo %shas been initialized in %s' | ||
332 | % (init_type, self.manifest.topdir)) | ||
333 | |||
334 | current_dir = os.getcwd() | ||
335 | if current_dir != self.manifest.topdir: | ||
336 | print('If this is not the directory in which you want to initialize ' | ||
337 | 'repo, please run:') | ||
338 | print(' rm -r %s/.repo' % self.manifest.topdir) | ||
339 | print('and try again.') | ||
340 | |||
316 | def Execute(self, opt, args): | 341 | def Execute(self, opt, args): |
317 | git_require(MIN_GIT_VERSION, fail=True) | 342 | git_require(MIN_GIT_VERSION, fail=True) |
318 | 343 | ||
@@ -329,10 +354,4 @@ to update the working directory files. | |||
329 | 354 | ||
330 | self._ConfigureDepth(opt) | 355 | self._ConfigureDepth(opt) |
331 | 356 | ||
332 | if self.manifest.IsMirror: | 357 | self._DisplayResult() |
333 | init_type = 'mirror ' | ||
334 | else: | ||
335 | init_type = '' | ||
336 | |||
337 | print '' | ||
338 | print 'repo %sinitialized in %s' % (init_type, self.manifest.topdir) | ||
diff --git a/subcmds/list.py b/subcmds/list.py index 6058a755..0d5c27f7 100644 --- a/subcmds/list.py +++ b/subcmds/list.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import re | 17 | import re |
17 | 18 | ||
18 | from command import Command, MirrorSafeCommand | 19 | from command import Command, MirrorSafeCommand |
@@ -64,7 +65,7 @@ This is similar to running: repo forall -c 'echo "$REPO_PATH : $REPO_PROJECT"'. | |||
64 | lines.append("%s : %s" % (_getpath(project), project.name)) | 65 | lines.append("%s : %s" % (_getpath(project), project.name)) |
65 | 66 | ||
66 | lines.sort() | 67 | lines.sort() |
67 | print '\n'.join(lines) | 68 | print('\n'.join(lines)) |
68 | 69 | ||
69 | def FindProjects(self, args): | 70 | def FindProjects(self, args): |
70 | result = [] | 71 | result = [] |
diff --git a/subcmds/manifest.py b/subcmds/manifest.py index 5592a37d..5ceeb12f 100644 --- a/subcmds/manifest.py +++ b/subcmds/manifest.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import os | 17 | import os |
17 | import sys | 18 | import sys |
18 | 19 | ||
@@ -69,7 +70,7 @@ in a Git repository for use during future 'repo init' invocations. | |||
69 | peg_rev_upstream = opt.peg_rev_upstream) | 70 | peg_rev_upstream = opt.peg_rev_upstream) |
70 | fd.close() | 71 | fd.close() |
71 | if opt.output_file != '-': | 72 | if opt.output_file != '-': |
72 | print >>sys.stderr, 'Saved manifest to %s' % opt.output_file | 73 | print('Saved manifest to %s' % opt.output_file, file=sys.stderr) |
73 | 74 | ||
74 | def Execute(self, opt, args): | 75 | def Execute(self, opt, args): |
75 | if args: | 76 | if args: |
@@ -79,6 +80,6 @@ in a Git repository for use during future 'repo init' invocations. | |||
79 | self._Output(opt) | 80 | self._Output(opt) |
80 | return | 81 | return |
81 | 82 | ||
82 | print >>sys.stderr, 'error: no operation to perform' | 83 | print('error: no operation to perform', file=sys.stderr) |
83 | print >>sys.stderr, 'error: see repo help manifest' | 84 | print('error: see repo help manifest', file=sys.stderr) |
84 | sys.exit(1) | 85 | sys.exit(1) |
diff --git a/subcmds/overview.py b/subcmds/overview.py index a509bd9a..418459ae 100644 --- a/subcmds/overview.py +++ b/subcmds/overview.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | from color import Coloring | 17 | from color import Coloring |
17 | from command import PagedCommand | 18 | from command import PagedCommand |
18 | 19 | ||
@@ -54,8 +55,11 @@ are displayed. | |||
54 | def __init__(self, config): | 55 | def __init__(self, config): |
55 | Coloring.__init__(self, config, 'status') | 56 | Coloring.__init__(self, config, 'status') |
56 | self.project = self.printer('header', attr='bold') | 57 | self.project = self.printer('header', attr='bold') |
58 | self.text = self.printer('text') | ||
57 | 59 | ||
58 | out = Report(all_branches[0].project.config) | 60 | out = Report(all_branches[0].project.config) |
61 | out.text("Deprecated. See repo info -o.") | ||
62 | out.nl() | ||
59 | out.project('Projects Overview') | 63 | out.project('Projects Overview') |
60 | out.nl() | 64 | out.nl() |
61 | 65 | ||
@@ -70,11 +74,11 @@ are displayed. | |||
70 | 74 | ||
71 | commits = branch.commits | 75 | commits = branch.commits |
72 | date = branch.date | 76 | date = branch.date |
73 | print '%s %-33s (%2d commit%s, %s)' % ( | 77 | print('%s %-33s (%2d commit%s, %s)' % ( |
74 | branch.name == project.CurrentBranch and '*' or ' ', | 78 | branch.name == project.CurrentBranch and '*' or ' ', |
75 | branch.name, | 79 | branch.name, |
76 | len(commits), | 80 | len(commits), |
77 | len(commits) != 1 and 's' or ' ', | 81 | len(commits) != 1 and 's' or ' ', |
78 | date) | 82 | date)) |
79 | for commit in commits: | 83 | for commit in commits: |
80 | print '%-35s - %s' % ('', commit) | 84 | print('%-35s - %s' % ('', commit)) |
diff --git a/subcmds/prune.py b/subcmds/prune.py index c50a5507..39c571a4 100644 --- a/subcmds/prune.py +++ b/subcmds/prune.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | from color import Coloring | 17 | from color import Coloring |
17 | from command import PagedCommand | 18 | from command import PagedCommand |
18 | 19 | ||
@@ -51,9 +52,9 @@ class Prune(PagedCommand): | |||
51 | 52 | ||
52 | commits = branch.commits | 53 | commits = branch.commits |
53 | date = branch.date | 54 | date = branch.date |
54 | print '%s %-33s (%2d commit%s, %s)' % ( | 55 | print('%s %-33s (%2d commit%s, %s)' % ( |
55 | branch.name == project.CurrentBranch and '*' or ' ', | 56 | branch.name == project.CurrentBranch and '*' or ' ', |
56 | branch.name, | 57 | branch.name, |
57 | len(commits), | 58 | len(commits), |
58 | len(commits) != 1 and 's' or ' ', | 59 | len(commits) != 1 and 's' or ' ', |
59 | date) | 60 | date)) |
diff --git a/subcmds/rebase.py b/subcmds/rebase.py index a8d58cdb..06cda22c 100644 --- a/subcmds/rebase.py +++ b/subcmds/rebase.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import sys | 17 | import sys |
17 | 18 | ||
18 | from command import Command | 19 | from command import Command |
@@ -59,14 +60,16 @@ branch but need to incorporate new upstream changes "underneath" them. | |||
59 | one_project = len(all_projects) == 1 | 60 | one_project = len(all_projects) == 1 |
60 | 61 | ||
61 | if opt.interactive and not one_project: | 62 | if opt.interactive and not one_project: |
62 | print >>sys.stderr, 'error: interactive rebase not supported with multiple projects' | 63 | print('error: interactive rebase not supported with multiple projects', |
64 | file=sys.stderr) | ||
63 | return -1 | 65 | return -1 |
64 | 66 | ||
65 | for project in all_projects: | 67 | for project in all_projects: |
66 | cb = project.CurrentBranch | 68 | cb = project.CurrentBranch |
67 | if not cb: | 69 | if not cb: |
68 | if one_project: | 70 | if one_project: |
69 | print >>sys.stderr, "error: project %s has a detatched HEAD" % project.relpath | 71 | print("error: project %s has a detatched HEAD" % project.relpath, |
72 | file=sys.stderr) | ||
70 | return -1 | 73 | return -1 |
71 | # ignore branches with detatched HEADs | 74 | # ignore branches with detatched HEADs |
72 | continue | 75 | continue |
@@ -74,7 +77,8 @@ branch but need to incorporate new upstream changes "underneath" them. | |||
74 | upbranch = project.GetBranch(cb) | 77 | upbranch = project.GetBranch(cb) |
75 | if not upbranch.LocalMerge: | 78 | if not upbranch.LocalMerge: |
76 | if one_project: | 79 | if one_project: |
77 | print >>sys.stderr, "error: project %s does not track any remote branches" % project.relpath | 80 | print("error: project %s does not track any remote branches" |
81 | % project.relpath, file=sys.stderr) | ||
78 | return -1 | 82 | return -1 |
79 | # ignore branches without remotes | 83 | # ignore branches without remotes |
80 | continue | 84 | continue |
@@ -101,8 +105,8 @@ branch but need to incorporate new upstream changes "underneath" them. | |||
101 | 105 | ||
102 | args.append(upbranch.LocalMerge) | 106 | args.append(upbranch.LocalMerge) |
103 | 107 | ||
104 | print >>sys.stderr, '# %s: rebasing %s -> %s' % \ | 108 | print('# %s: rebasing %s -> %s' |
105 | (project.relpath, cb, upbranch.LocalMerge) | 109 | % (project.relpath, cb, upbranch.LocalMerge), file=sys.stderr) |
106 | 110 | ||
107 | needs_stash = False | 111 | needs_stash = False |
108 | if opt.auto_stash: | 112 | if opt.auto_stash: |
diff --git a/subcmds/selfupdate.py b/subcmds/selfupdate.py index 46aa3a19..d12e08d0 100644 --- a/subcmds/selfupdate.py +++ b/subcmds/selfupdate.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | from optparse import SUPPRESS_HELP | 17 | from optparse import SUPPRESS_HELP |
17 | import sys | 18 | import sys |
18 | 19 | ||
@@ -52,7 +53,7 @@ need to be performed by an end-user. | |||
52 | 53 | ||
53 | else: | 54 | else: |
54 | if not rp.Sync_NetworkHalf(): | 55 | if not rp.Sync_NetworkHalf(): |
55 | print >>sys.stderr, "error: can't update repo" | 56 | print("error: can't update repo", file=sys.stderr) |
56 | sys.exit(1) | 57 | sys.exit(1) |
57 | 58 | ||
58 | rp.bare_git.gc('--auto') | 59 | rp.bare_git.gc('--auto') |
diff --git a/subcmds/stage.py b/subcmds/stage.py index 2ec48069..ff15ee0c 100644 --- a/subcmds/stage.py +++ b/subcmds/stage.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import sys | 17 | import sys |
17 | 18 | ||
18 | from color import Coloring | 19 | from color import Coloring |
@@ -50,7 +51,7 @@ The '%prog' command stages files to prepare the next commit. | |||
50 | def _Interactive(self, opt, args): | 51 | def _Interactive(self, opt, args): |
51 | all_projects = filter(lambda x: x.IsDirty(), self.GetProjects(args)) | 52 | all_projects = filter(lambda x: x.IsDirty(), self.GetProjects(args)) |
52 | if not all_projects: | 53 | if not all_projects: |
53 | print >>sys.stderr,'no projects have uncommitted modifications' | 54 | print('no projects have uncommitted modifications', file=sys.stderr) |
54 | return | 55 | return |
55 | 56 | ||
56 | out = _ProjectList(self.manifest.manifestProject.config) | 57 | out = _ProjectList(self.manifest.manifestProject.config) |
@@ -58,7 +59,7 @@ The '%prog' command stages files to prepare the next commit. | |||
58 | out.header(' %s', 'project') | 59 | out.header(' %s', 'project') |
59 | out.nl() | 60 | out.nl() |
60 | 61 | ||
61 | for i in xrange(0, len(all_projects)): | 62 | for i in range(len(all_projects)): |
62 | p = all_projects[i] | 63 | p = all_projects[i] |
63 | out.write('%3d: %s', i + 1, p.relpath + '/') | 64 | out.write('%3d: %s', i + 1, p.relpath + '/') |
64 | out.nl() | 65 | out.nl() |
@@ -101,7 +102,7 @@ The '%prog' command stages files to prepare the next commit. | |||
101 | if len(p) == 1: | 102 | if len(p) == 1: |
102 | _AddI(p[0]) | 103 | _AddI(p[0]) |
103 | continue | 104 | continue |
104 | print 'Bye.' | 105 | print('Bye.') |
105 | 106 | ||
106 | def _AddI(project): | 107 | def _AddI(project): |
107 | p = GitCommand(project, ['add', '--interactive'], bare=False) | 108 | p = GitCommand(project, ['add', '--interactive'], bare=False) |
diff --git a/subcmds/start.py b/subcmds/start.py index be645314..2d723fc2 100644 --- a/subcmds/start.py +++ b/subcmds/start.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import sys | 17 | import sys |
17 | from command import Command | 18 | from command import Command |
18 | from git_config import IsId | 19 | from git_config import IsId |
@@ -41,7 +42,7 @@ revision specified in the manifest. | |||
41 | 42 | ||
42 | nb = args[0] | 43 | nb = args[0] |
43 | if not git.check_ref_format('heads/%s' % nb): | 44 | if not git.check_ref_format('heads/%s' % nb): |
44 | print >>sys.stderr, "error: '%s' is not a valid name" % nb | 45 | print("error: '%s' is not a valid name" % nb, file=sys.stderr) |
45 | sys.exit(1) | 46 | sys.exit(1) |
46 | 47 | ||
47 | err = [] | 48 | err = [] |
@@ -49,7 +50,7 @@ revision specified in the manifest. | |||
49 | if not opt.all: | 50 | if not opt.all: |
50 | projects = args[1:] | 51 | projects = args[1:] |
51 | if len(projects) < 1: | 52 | if len(projects) < 1: |
52 | print >>sys.stderr, "error: at least one project must be specified" | 53 | print("error: at least one project must be specified", file=sys.stderr) |
53 | sys.exit(1) | 54 | sys.exit(1) |
54 | 55 | ||
55 | all_projects = self.GetProjects(projects) | 56 | all_projects = self.GetProjects(projects) |
@@ -67,7 +68,6 @@ revision specified in the manifest. | |||
67 | 68 | ||
68 | if err: | 69 | if err: |
69 | for p in err: | 70 | for p in err: |
70 | print >>sys.stderr,\ | 71 | print("error: %s/: cannot start %s" % (p.relpath, nb), |
71 | "error: %s/: cannot start %s" \ | 72 | file=sys.stderr) |
72 | % (p.relpath, nb) | ||
73 | sys.exit(1) | 73 | sys.exit(1) |
diff --git a/subcmds/status.py b/subcmds/status.py index 7611621e..cce00c81 100644 --- a/subcmds/status.py +++ b/subcmds/status.py | |||
@@ -20,10 +20,14 @@ try: | |||
20 | except ImportError: | 20 | except ImportError: |
21 | import dummy_threading as _threading | 21 | import dummy_threading as _threading |
22 | 22 | ||
23 | import glob | ||
23 | import itertools | 24 | import itertools |
25 | import os | ||
24 | import sys | 26 | import sys |
25 | import StringIO | 27 | import StringIO |
26 | 28 | ||
29 | from color import Coloring | ||
30 | |||
27 | class Status(PagedCommand): | 31 | class Status(PagedCommand): |
28 | common = True | 32 | common = True |
29 | helpSummary = "Show the working tree status" | 33 | helpSummary = "Show the working tree status" |
@@ -39,6 +43,13 @@ is a difference between these three states. | |||
39 | The -j/--jobs option can be used to run multiple status queries | 43 | The -j/--jobs option can be used to run multiple status queries |
40 | in parallel. | 44 | in parallel. |
41 | 45 | ||
46 | The -o/--orphans option can be used to show objects that are in | ||
47 | the working directory, but not associated with a repo project. | ||
48 | This includes unmanaged top-level files and directories, but also | ||
49 | includes deeper items. For example, if dir/subdir/proj1 and | ||
50 | dir/subdir/proj2 are repo projects, dir/subdir/proj3 will be shown | ||
51 | if it is not known to repo. | ||
52 | |||
42 | Status Display | 53 | Status Display |
43 | -------------- | 54 | -------------- |
44 | 55 | ||
@@ -76,6 +87,9 @@ the following meanings: | |||
76 | p.add_option('-j', '--jobs', | 87 | p.add_option('-j', '--jobs', |
77 | dest='jobs', action='store', type='int', default=2, | 88 | dest='jobs', action='store', type='int', default=2, |
78 | help="number of projects to check simultaneously") | 89 | help="number of projects to check simultaneously") |
90 | p.add_option('-o', '--orphans', | ||
91 | dest='orphans', action='store_true', | ||
92 | help="include objects in working directory outside of repo projects") | ||
79 | 93 | ||
80 | def _StatusHelper(self, project, clean_counter, sem, output): | 94 | def _StatusHelper(self, project, clean_counter, sem, output): |
81 | """Obtains the status for a specific project. | 95 | """Obtains the status for a specific project. |
@@ -97,6 +111,22 @@ the following meanings: | |||
97 | finally: | 111 | finally: |
98 | sem.release() | 112 | sem.release() |
99 | 113 | ||
114 | def _FindOrphans(self, dirs, proj_dirs, proj_dirs_parents, outstring): | ||
115 | """find 'dirs' that are present in 'proj_dirs_parents' but not in 'proj_dirs'""" | ||
116 | status_header = ' --\t' | ||
117 | for item in dirs: | ||
118 | if not os.path.isdir(item): | ||
119 | outstring.write(''.join([status_header, item])) | ||
120 | continue | ||
121 | if item in proj_dirs: | ||
122 | continue | ||
123 | if item in proj_dirs_parents: | ||
124 | self._FindOrphans(glob.glob('%s/.*' % item) + \ | ||
125 | glob.glob('%s/*' % item), \ | ||
126 | proj_dirs, proj_dirs_parents, outstring) | ||
127 | continue | ||
128 | outstring.write(''.join([status_header, item, '/'])) | ||
129 | |||
100 | def Execute(self, opt, args): | 130 | def Execute(self, opt, args): |
101 | all_projects = self.GetProjects(args) | 131 | all_projects = self.GetProjects(args) |
102 | counter = itertools.count() | 132 | counter = itertools.count() |
@@ -129,4 +159,46 @@ the following meanings: | |||
129 | output.dump(sys.stdout) | 159 | output.dump(sys.stdout) |
130 | output.close() | 160 | output.close() |
131 | if len(all_projects) == counter.next(): | 161 | if len(all_projects) == counter.next(): |
132 | print 'nothing to commit (working directory clean)' | 162 | print('nothing to commit (working directory clean)') |
163 | |||
164 | if opt.orphans: | ||
165 | proj_dirs = set() | ||
166 | proj_dirs_parents = set() | ||
167 | for project in self.GetProjects(None, missing_ok=True): | ||
168 | proj_dirs.add(project.relpath) | ||
169 | (head, _tail) = os.path.split(project.relpath) | ||
170 | while head != "": | ||
171 | proj_dirs_parents.add(head) | ||
172 | (head, _tail) = os.path.split(head) | ||
173 | proj_dirs.add('.repo') | ||
174 | |||
175 | class StatusColoring(Coloring): | ||
176 | def __init__(self, config): | ||
177 | Coloring.__init__(self, config, 'status') | ||
178 | self.project = self.printer('header', attr = 'bold') | ||
179 | self.untracked = self.printer('untracked', fg = 'red') | ||
180 | |||
181 | orig_path = os.getcwd() | ||
182 | try: | ||
183 | os.chdir(self.manifest.topdir) | ||
184 | |||
185 | outstring = StringIO.StringIO() | ||
186 | self._FindOrphans(glob.glob('.*') + \ | ||
187 | glob.glob('*'), \ | ||
188 | proj_dirs, proj_dirs_parents, outstring) | ||
189 | |||
190 | if outstring.buflist: | ||
191 | output = StatusColoring(self.manifest.globalConfig) | ||
192 | output.project('Objects not within a project (orphans)') | ||
193 | output.nl() | ||
194 | for entry in outstring.buflist: | ||
195 | output.untracked(entry) | ||
196 | output.nl() | ||
197 | else: | ||
198 | print('No orphan files or directories') | ||
199 | |||
200 | outstring.close() | ||
201 | |||
202 | finally: | ||
203 | # Restore CWD. | ||
204 | os.chdir(orig_path) | ||
diff --git a/subcmds/sync.py b/subcmds/sync.py index d4637d0c..228a279a 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import netrc | 17 | import netrc |
17 | from optparse import SUPPRESS_HELP | 18 | from optparse import SUPPRESS_HELP |
18 | import os | 19 | import os |
@@ -44,13 +45,13 @@ try: | |||
44 | except ImportError: | 45 | except ImportError: |
45 | multiprocessing = None | 46 | multiprocessing = None |
46 | 47 | ||
47 | from git_command import GIT | 48 | from git_command import GIT, git_require |
48 | from git_refs import R_HEADS, HEAD | 49 | from git_refs import R_HEADS, HEAD |
49 | from main import WrapperModule | 50 | from main import WrapperModule |
50 | from project import Project | 51 | from project import Project |
51 | from project import RemoteSpec | 52 | from project import RemoteSpec |
52 | from command import Command, MirrorSafeCommand | 53 | from command import Command, MirrorSafeCommand |
53 | from error import RepoChangedException, GitError | 54 | from error import RepoChangedException, GitError, ManifestParseError |
54 | from project import SyncBuffer | 55 | from project import SyncBuffer |
55 | from progress import Progress | 56 | from progress import Progress |
56 | 57 | ||
@@ -113,6 +114,9 @@ resumeable bundle file on a content delivery network. This | |||
113 | may be necessary if there are problems with the local Python | 114 | may be necessary if there are problems with the local Python |
114 | HTTP client or proxy configuration, but the Git binary works. | 115 | HTTP client or proxy configuration, but the Git binary works. |
115 | 116 | ||
117 | The --fetch-submodules option enables fetching Git submodules | ||
118 | of a project from server. | ||
119 | |||
116 | SSH Connections | 120 | SSH Connections |
117 | --------------- | 121 | --------------- |
118 | 122 | ||
@@ -144,27 +148,30 @@ later is required to fix a server side protocol bug. | |||
144 | """ | 148 | """ |
145 | 149 | ||
146 | def _Options(self, p, show_smart=True): | 150 | def _Options(self, p, show_smart=True): |
147 | self.jobs = self.manifest.default.sync_j | 151 | try: |
152 | self.jobs = self.manifest.default.sync_j | ||
153 | except ManifestParseError: | ||
154 | self.jobs = 1 | ||
148 | 155 | ||
149 | p.add_option('-f', '--force-broken', | 156 | p.add_option('-f', '--force-broken', |
150 | dest='force_broken', action='store_true', | 157 | dest='force_broken', action='store_true', |
151 | help="continue sync even if a project fails to sync") | 158 | help="continue sync even if a project fails to sync") |
152 | p.add_option('-l','--local-only', | 159 | p.add_option('-l', '--local-only', |
153 | dest='local_only', action='store_true', | 160 | dest='local_only', action='store_true', |
154 | help="only update working tree, don't fetch") | 161 | help="only update working tree, don't fetch") |
155 | p.add_option('-n','--network-only', | 162 | p.add_option('-n', '--network-only', |
156 | dest='network_only', action='store_true', | 163 | dest='network_only', action='store_true', |
157 | help="fetch only, don't update working tree") | 164 | help="fetch only, don't update working tree") |
158 | p.add_option('-d','--detach', | 165 | p.add_option('-d', '--detach', |
159 | dest='detach_head', action='store_true', | 166 | dest='detach_head', action='store_true', |
160 | help='detach projects back to manifest revision') | 167 | help='detach projects back to manifest revision') |
161 | p.add_option('-c','--current-branch', | 168 | p.add_option('-c', '--current-branch', |
162 | dest='current_branch_only', action='store_true', | 169 | dest='current_branch_only', action='store_true', |
163 | help='fetch only current branch from server') | 170 | help='fetch only current branch from server') |
164 | p.add_option('-q','--quiet', | 171 | p.add_option('-q', '--quiet', |
165 | dest='quiet', action='store_true', | 172 | dest='quiet', action='store_true', |
166 | help='be more quiet') | 173 | help='be more quiet') |
167 | p.add_option('-j','--jobs', | 174 | p.add_option('-j', '--jobs', |
168 | dest='jobs', action='store', type='int', | 175 | dest='jobs', action='store', type='int', |
169 | help="projects to fetch simultaneously (default %d)" % self.jobs) | 176 | help="projects to fetch simultaneously (default %d)" % self.jobs) |
170 | p.add_option('-m', '--manifest-name', | 177 | p.add_option('-m', '--manifest-name', |
@@ -173,6 +180,15 @@ later is required to fix a server side protocol bug. | |||
173 | p.add_option('--no-clone-bundle', | 180 | p.add_option('--no-clone-bundle', |
174 | dest='no_clone_bundle', action='store_true', | 181 | dest='no_clone_bundle', action='store_true', |
175 | help='disable use of /clone.bundle on HTTP/HTTPS') | 182 | help='disable use of /clone.bundle on HTTP/HTTPS') |
183 | p.add_option('-u', '--manifest-server-username', action='store', | ||
184 | dest='manifest_server_username', | ||
185 | help='username to authenticate with the manifest server') | ||
186 | p.add_option('-p', '--manifest-server-password', action='store', | ||
187 | dest='manifest_server_password', | ||
188 | help='password to authenticate with the manifest server') | ||
189 | p.add_option('--fetch-submodules', | ||
190 | dest='fetch_submodules', action='store_true', | ||
191 | help='fetch submodules from server') | ||
176 | if show_smart: | 192 | if show_smart: |
177 | p.add_option('-s', '--smart-sync', | 193 | p.add_option('-s', '--smart-sync', |
178 | dest='smart_sync', action='store_true', | 194 | dest='smart_sync', action='store_true', |
@@ -180,12 +196,6 @@ later is required to fix a server side protocol bug. | |||
180 | p.add_option('-t', '--smart-tag', | 196 | p.add_option('-t', '--smart-tag', |
181 | dest='smart_tag', action='store', | 197 | dest='smart_tag', action='store', |
182 | help='smart sync using manifest from a known tag') | 198 | help='smart sync using manifest from a known tag') |
183 | p.add_option('-u', '--manifest-server-username', action='store', | ||
184 | dest='manifest_server_username', | ||
185 | help='username to authenticate with the manifest server') | ||
186 | p.add_option('-p', '--manifest-server-password', action='store', | ||
187 | dest='manifest_server_password', | ||
188 | help='password to authenticate with the manifest server') | ||
189 | 199 | ||
190 | g = p.add_option_group('repo Version options') | 200 | g = p.add_option_group('repo Version options') |
191 | g.add_option('--no-repo-verify', | 201 | g.add_option('--no-repo-verify', |
@@ -196,61 +206,62 @@ later is required to fix a server side protocol bug. | |||
196 | help=SUPPRESS_HELP) | 206 | help=SUPPRESS_HELP) |
197 | 207 | ||
198 | def _FetchHelper(self, opt, project, lock, fetched, pm, sem, err_event): | 208 | def _FetchHelper(self, opt, project, lock, fetched, pm, sem, err_event): |
199 | """Main function of the fetch threads when jobs are > 1. | 209 | """Main function of the fetch threads when jobs are > 1. |
200 | 210 | ||
201 | Args: | 211 | Args: |
202 | opt: Program options returned from optparse. See _Options(). | 212 | opt: Program options returned from optparse. See _Options(). |
203 | project: Project object for the project to fetch. | 213 | project: Project object for the project to fetch. |
204 | lock: Lock for accessing objects that are shared amongst multiple | 214 | lock: Lock for accessing objects that are shared amongst multiple |
205 | _FetchHelper() threads. | 215 | _FetchHelper() threads. |
206 | fetched: set object that we will add project.gitdir to when we're done | 216 | fetched: set object that we will add project.gitdir to when we're done |
207 | (with our lock held). | 217 | (with our lock held). |
208 | pm: Instance of a Project object. We will call pm.update() (with our | 218 | pm: Instance of a Project object. We will call pm.update() (with our |
209 | lock held). | 219 | lock held). |
210 | sem: We'll release() this semaphore when we exit so that another thread | 220 | sem: We'll release() this semaphore when we exit so that another thread |
211 | can be started up. | 221 | can be started up. |
212 | err_event: We'll set this event in the case of an error (after printing | 222 | err_event: We'll set this event in the case of an error (after printing |
213 | out info about the error). | 223 | out info about the error). |
214 | """ | 224 | """ |
215 | # We'll set to true once we've locked the lock. | 225 | # We'll set to true once we've locked the lock. |
216 | did_lock = False | 226 | did_lock = False |
217 | 227 | ||
218 | # Encapsulate everything in a try/except/finally so that: | 228 | # Encapsulate everything in a try/except/finally so that: |
219 | # - We always set err_event in the case of an exception. | 229 | # - We always set err_event in the case of an exception. |
220 | # - We always make sure we call sem.release(). | 230 | # - We always make sure we call sem.release(). |
221 | # - We always make sure we unlock the lock if we locked it. | 231 | # - We always make sure we unlock the lock if we locked it. |
232 | try: | ||
222 | try: | 233 | try: |
223 | try: | 234 | start = time.time() |
224 | start = time.time() | 235 | success = project.Sync_NetworkHalf( |
225 | success = project.Sync_NetworkHalf( | 236 | quiet=opt.quiet, |
226 | quiet=opt.quiet, | 237 | current_branch_only=opt.current_branch_only, |
227 | current_branch_only=opt.current_branch_only, | 238 | clone_bundle=not opt.no_clone_bundle) |
228 | clone_bundle=not opt.no_clone_bundle) | 239 | self._fetch_times.Set(project, time.time() - start) |
229 | self._fetch_times.Set(project, time.time() - start) | 240 | |
230 | 241 | # Lock around all the rest of the code, since printing, updating a set | |
231 | # Lock around all the rest of the code, since printing, updating a set | 242 | # and Progress.update() are not thread safe. |
232 | # and Progress.update() are not thread safe. | 243 | lock.acquire() |
233 | lock.acquire() | 244 | did_lock = True |
234 | did_lock = True | 245 | |
235 | 246 | if not success: | |
236 | if not success: | 247 | print('error: Cannot fetch %s' % project.name, file=sys.stderr) |
237 | print >>sys.stderr, 'error: Cannot fetch %s' % project.name | 248 | if opt.force_broken: |
238 | if opt.force_broken: | 249 | print('warn: --force-broken, continuing to sync', |
239 | print >>sys.stderr, 'warn: --force-broken, continuing to sync' | 250 | file=sys.stderr) |
240 | else: | 251 | else: |
241 | raise _FetchError() | 252 | raise _FetchError() |
242 | 253 | ||
243 | fetched.add(project.gitdir) | 254 | fetched.add(project.gitdir) |
244 | pm.update() | 255 | pm.update() |
245 | except _FetchError: | 256 | except _FetchError: |
246 | err_event.set() | 257 | err_event.set() |
247 | except: | 258 | except: |
248 | err_event.set() | 259 | err_event.set() |
249 | raise | 260 | raise |
250 | finally: | 261 | finally: |
251 | if did_lock: | 262 | if did_lock: |
252 | lock.release() | 263 | lock.release() |
253 | sem.release() | 264 | sem.release() |
254 | 265 | ||
255 | def _Fetch(self, projects, opt): | 266 | def _Fetch(self, projects, opt): |
256 | fetched = set() | 267 | fetched = set() |
@@ -265,9 +276,9 @@ later is required to fix a server side protocol bug. | |||
265 | clone_bundle=not opt.no_clone_bundle): | 276 | clone_bundle=not opt.no_clone_bundle): |
266 | fetched.add(project.gitdir) | 277 | fetched.add(project.gitdir) |
267 | else: | 278 | else: |
268 | print >>sys.stderr, 'error: Cannot fetch %s' % project.name | 279 | print('error: Cannot fetch %s' % project.name, file=sys.stderr) |
269 | if opt.force_broken: | 280 | if opt.force_broken: |
270 | print >>sys.stderr, 'warn: --force-broken, continuing to sync' | 281 | print('warn: --force-broken, continuing to sync', file=sys.stderr) |
271 | else: | 282 | else: |
272 | sys.exit(1) | 283 | sys.exit(1) |
273 | else: | 284 | else: |
@@ -300,7 +311,7 @@ later is required to fix a server side protocol bug. | |||
300 | 311 | ||
301 | # If we saw an error, exit with code 1 so that other scripts can check. | 312 | # If we saw an error, exit with code 1 so that other scripts can check. |
302 | if err_event.isSet(): | 313 | if err_event.isSet(): |
303 | print >>sys.stderr, '\nerror: Exited sync due to fetch errors' | 314 | print('\nerror: Exited sync due to fetch errors', file=sys.stderr) |
304 | sys.exit(1) | 315 | sys.exit(1) |
305 | 316 | ||
306 | pm.end() | 317 | pm.end() |
@@ -310,7 +321,8 @@ later is required to fix a server side protocol bug. | |||
310 | return fetched | 321 | return fetched |
311 | 322 | ||
312 | def _GCProjects(self, projects): | 323 | def _GCProjects(self, projects): |
313 | if multiprocessing: | 324 | has_dash_c = git_require((1, 7, 2)) |
325 | if multiprocessing and has_dash_c: | ||
314 | cpu_count = multiprocessing.cpu_count() | 326 | cpu_count = multiprocessing.cpu_count() |
315 | else: | 327 | else: |
316 | cpu_count = 1 | 328 | cpu_count = 1 |
@@ -352,7 +364,7 @@ later is required to fix a server side protocol bug. | |||
352 | t.join() | 364 | t.join() |
353 | 365 | ||
354 | if err_event.isSet(): | 366 | if err_event.isSet(): |
355 | print >>sys.stderr, '\nerror: Exited sync due to gc errors' | 367 | print('\nerror: Exited sync due to gc errors', file=sys.stderr) |
356 | sys.exit(1) | 368 | sys.exit(1) |
357 | 369 | ||
358 | def UpdateProjectList(self): | 370 | def UpdateProjectList(self): |
@@ -376,34 +388,36 @@ later is required to fix a server side protocol bug. | |||
376 | if path not in new_project_paths: | 388 | if path not in new_project_paths: |
377 | # If the path has already been deleted, we don't need to do it | 389 | # If the path has already been deleted, we don't need to do it |
378 | if os.path.exists(self.manifest.topdir + '/' + path): | 390 | if os.path.exists(self.manifest.topdir + '/' + path): |
379 | project = Project( | 391 | project = Project( |
380 | manifest = self.manifest, | 392 | manifest = self.manifest, |
381 | name = path, | 393 | name = path, |
382 | remote = RemoteSpec('origin'), | 394 | remote = RemoteSpec('origin'), |
383 | gitdir = os.path.join(self.manifest.topdir, | 395 | gitdir = os.path.join(self.manifest.topdir, |
384 | path, '.git'), | 396 | path, '.git'), |
385 | worktree = os.path.join(self.manifest.topdir, path), | 397 | worktree = os.path.join(self.manifest.topdir, path), |
386 | relpath = path, | 398 | relpath = path, |
387 | revisionExpr = 'HEAD', | 399 | revisionExpr = 'HEAD', |
388 | revisionId = None, | 400 | revisionId = None, |
389 | groups = None) | 401 | groups = None) |
390 | 402 | ||
391 | if project.IsDirty(): | 403 | if project.IsDirty(): |
392 | print >>sys.stderr, 'error: Cannot remove project "%s": \ | 404 | print('error: Cannot remove project "%s": uncommitted changes' |
393 | uncommitted changes are present' % project.relpath | 405 | 'are present' % project.relpath, file=sys.stderr) |
394 | print >>sys.stderr, ' commit changes, then run sync again' | 406 | print(' commit changes, then run sync again', |
395 | return -1 | 407 | file=sys.stderr) |
396 | else: | 408 | return -1 |
397 | print >>sys.stderr, 'Deleting obsolete path %s' % project.worktree | 409 | else: |
398 | shutil.rmtree(project.worktree) | 410 | print('Deleting obsolete path %s' % project.worktree, |
399 | # Try deleting parent subdirs if they are empty | 411 | file=sys.stderr) |
400 | project_dir = os.path.dirname(project.worktree) | 412 | shutil.rmtree(project.worktree) |
401 | while project_dir != self.manifest.topdir: | 413 | # Try deleting parent subdirs if they are empty |
402 | try: | 414 | project_dir = os.path.dirname(project.worktree) |
403 | os.rmdir(project_dir) | 415 | while project_dir != self.manifest.topdir: |
404 | except OSError: | 416 | try: |
405 | break | 417 | os.rmdir(project_dir) |
406 | project_dir = os.path.dirname(project_dir) | 418 | except OSError: |
419 | break | ||
420 | project_dir = os.path.dirname(project_dir) | ||
407 | 421 | ||
408 | new_project_paths.sort() | 422 | new_project_paths.sort() |
409 | fd = open(file_path, 'w') | 423 | fd = open(file_path, 'w') |
@@ -422,24 +436,24 @@ uncommitted changes are present' % project.relpath | |||
422 | self.jobs = min(self.jobs, (soft_limit - 5) / 3) | 436 | self.jobs = min(self.jobs, (soft_limit - 5) / 3) |
423 | 437 | ||
424 | if opt.network_only and opt.detach_head: | 438 | if opt.network_only and opt.detach_head: |
425 | print >>sys.stderr, 'error: cannot combine -n and -d' | 439 | print('error: cannot combine -n and -d', file=sys.stderr) |
426 | sys.exit(1) | 440 | sys.exit(1) |
427 | if opt.network_only and opt.local_only: | 441 | if opt.network_only and opt.local_only: |
428 | print >>sys.stderr, 'error: cannot combine -n and -l' | 442 | print('error: cannot combine -n and -l', file=sys.stderr) |
429 | sys.exit(1) | 443 | sys.exit(1) |
430 | if opt.manifest_name and opt.smart_sync: | 444 | if opt.manifest_name and opt.smart_sync: |
431 | print >>sys.stderr, 'error: cannot combine -m and -s' | 445 | print('error: cannot combine -m and -s', file=sys.stderr) |
432 | sys.exit(1) | 446 | sys.exit(1) |
433 | if opt.manifest_name and opt.smart_tag: | 447 | if opt.manifest_name and opt.smart_tag: |
434 | print >>sys.stderr, 'error: cannot combine -m and -t' | 448 | print('error: cannot combine -m and -t', file=sys.stderr) |
435 | sys.exit(1) | 449 | sys.exit(1) |
436 | if opt.manifest_server_username or opt.manifest_server_password: | 450 | if opt.manifest_server_username or opt.manifest_server_password: |
437 | if not (opt.smart_sync or opt.smart_tag): | 451 | if not (opt.smart_sync or opt.smart_tag): |
438 | print >>sys.stderr, 'error: -u and -p may only be combined with ' \ | 452 | print('error: -u and -p may only be combined with -s or -t', |
439 | '-s or -t' | 453 | file=sys.stderr) |
440 | sys.exit(1) | 454 | sys.exit(1) |
441 | if None in [opt.manifest_server_username, opt.manifest_server_password]: | 455 | if None in [opt.manifest_server_username, opt.manifest_server_password]: |
442 | print >>sys.stderr, 'error: both -u and -p must be given' | 456 | print('error: both -u and -p must be given', file=sys.stderr) |
443 | sys.exit(1) | 457 | sys.exit(1) |
444 | 458 | ||
445 | if opt.manifest_name: | 459 | if opt.manifest_name: |
@@ -447,8 +461,8 @@ uncommitted changes are present' % project.relpath | |||
447 | 461 | ||
448 | if opt.smart_sync or opt.smart_tag: | 462 | if opt.smart_sync or opt.smart_tag: |
449 | if not self.manifest.manifest_server: | 463 | if not self.manifest.manifest_server: |
450 | print >>sys.stderr, \ | 464 | print('error: cannot smart sync: no manifest server defined in' |
451 | 'error: cannot smart sync: no manifest server defined in manifest' | 465 | 'manifest', file=sys.stderr) |
452 | sys.exit(1) | 466 | sys.exit(1) |
453 | 467 | ||
454 | manifest_server = self.manifest.manifest_server | 468 | manifest_server = self.manifest.manifest_server |
@@ -463,7 +477,8 @@ uncommitted changes are present' % project.relpath | |||
463 | try: | 477 | try: |
464 | info = netrc.netrc() | 478 | info = netrc.netrc() |
465 | except IOError: | 479 | except IOError: |
466 | print >>sys.stderr, '.netrc file does not exist or could not be opened' | 480 | print('.netrc file does not exist or could not be opened', |
481 | file=sys.stderr) | ||
467 | else: | 482 | else: |
468 | try: | 483 | try: |
469 | parse_result = urlparse.urlparse(manifest_server) | 484 | parse_result = urlparse.urlparse(manifest_server) |
@@ -473,10 +488,10 @@ uncommitted changes are present' % project.relpath | |||
473 | except TypeError: | 488 | except TypeError: |
474 | # TypeError is raised when the given hostname is not present | 489 | # TypeError is raised when the given hostname is not present |
475 | # in the .netrc file. | 490 | # in the .netrc file. |
476 | print >>sys.stderr, 'No credentials found for %s in .netrc' % \ | 491 | print('No credentials found for %s in .netrc' |
477 | parse_result.hostname | 492 | % parse_result.hostname, file=sys.stderr) |
478 | except netrc.NetrcParseError as e: | 493 | except netrc.NetrcParseError as e: |
479 | print >>sys.stderr, 'Error parsing .netrc file: %s' % e | 494 | print('Error parsing .netrc file: %s' % e, file=sys.stderr) |
480 | 495 | ||
481 | if (username and password): | 496 | if (username and password): |
482 | manifest_server = manifest_server.replace('://', '://%s:%s@' % | 497 | manifest_server = manifest_server.replace('://', '://%s:%s@' % |
@@ -515,20 +530,21 @@ uncommitted changes are present' % project.relpath | |||
515 | finally: | 530 | finally: |
516 | f.close() | 531 | f.close() |
517 | except IOError: | 532 | except IOError: |
518 | print >>sys.stderr, 'error: cannot write manifest to %s' % \ | 533 | print('error: cannot write manifest to %s' % manifest_path, |
519 | manifest_path | 534 | file=sys.stderr) |
520 | sys.exit(1) | 535 | sys.exit(1) |
521 | self.manifest.Override(manifest_name) | 536 | self.manifest.Override(manifest_name) |
522 | else: | 537 | else: |
523 | print >>sys.stderr, 'error: %s' % manifest_str | 538 | print('error: %s' % manifest_str, file=sys.stderr) |
524 | sys.exit(1) | 539 | sys.exit(1) |
525 | except (socket.error, IOError, xmlrpclib.Fault) as e: | 540 | except (socket.error, IOError, xmlrpclib.Fault) as e: |
526 | print >>sys.stderr, 'error: cannot connect to manifest server %s:\n%s' % ( | 541 | print('error: cannot connect to manifest server %s:\n%s' |
527 | self.manifest.manifest_server, e) | 542 | % (self.manifest.manifest_server, e), file=sys.stderr) |
528 | sys.exit(1) | 543 | sys.exit(1) |
529 | except xmlrpclib.ProtocolError as e: | 544 | except xmlrpclib.ProtocolError as e: |
530 | print >>sys.stderr, 'error: cannot connect to manifest server %s:\n%d %s' % ( | 545 | print('error: cannot connect to manifest server %s:\n%d %s' |
531 | self.manifest.manifest_server, e.errcode, e.errmsg) | 546 | % (self.manifest.manifest_server, e.errcode, e.errmsg), |
547 | file=sys.stderr) | ||
532 | sys.exit(1) | 548 | sys.exit(1) |
533 | 549 | ||
534 | rp = self.manifest.repoProject | 550 | rp = self.manifest.repoProject |
@@ -552,7 +568,9 @@ uncommitted changes are present' % project.relpath | |||
552 | self.manifest._Unload() | 568 | self.manifest._Unload() |
553 | if opt.jobs is None: | 569 | if opt.jobs is None: |
554 | self.jobs = self.manifest.default.sync_j | 570 | self.jobs = self.manifest.default.sync_j |
555 | all_projects = self.GetProjects(args, missing_ok=True) | 571 | all_projects = self.GetProjects(args, |
572 | missing_ok=True, | ||
573 | submodules_ok=opt.fetch_submodules) | ||
556 | 574 | ||
557 | self._fetch_times = _FetchTimes(self.manifest) | 575 | self._fetch_times = _FetchTimes(self.manifest) |
558 | if not opt.local_only: | 576 | if not opt.local_only: |
@@ -563,12 +581,33 @@ uncommitted changes are present' % project.relpath | |||
563 | to_fetch.extend(all_projects) | 581 | to_fetch.extend(all_projects) |
564 | to_fetch.sort(key=self._fetch_times.Get, reverse=True) | 582 | to_fetch.sort(key=self._fetch_times.Get, reverse=True) |
565 | 583 | ||
566 | self._Fetch(to_fetch, opt) | 584 | fetched = self._Fetch(to_fetch, opt) |
567 | _PostRepoFetch(rp, opt.no_repo_verify) | 585 | _PostRepoFetch(rp, opt.no_repo_verify) |
568 | if opt.network_only: | 586 | if opt.network_only: |
569 | # bail out now; the rest touches the working tree | 587 | # bail out now; the rest touches the working tree |
570 | return | 588 | return |
571 | 589 | ||
590 | # Iteratively fetch missing and/or nested unregistered submodules | ||
591 | previously_missing_set = set() | ||
592 | while True: | ||
593 | self.manifest._Unload() | ||
594 | all_projects = self.GetProjects(args, | ||
595 | missing_ok=True, | ||
596 | submodules_ok=opt.fetch_submodules) | ||
597 | missing = [] | ||
598 | for project in all_projects: | ||
599 | if project.gitdir not in fetched: | ||
600 | missing.append(project) | ||
601 | if not missing: | ||
602 | break | ||
603 | # Stop us from non-stopped fetching actually-missing repos: If set of | ||
604 | # missing repos has not been changed from last fetch, we break. | ||
605 | missing_set = set(p.name for p in missing) | ||
606 | if previously_missing_set == missing_set: | ||
607 | break | ||
608 | previously_missing_set = missing_set | ||
609 | fetched.update(self._Fetch(missing, opt)) | ||
610 | |||
572 | if self.manifest.IsMirror: | 611 | if self.manifest.IsMirror: |
573 | # bail out now, we have no working tree | 612 | # bail out now, we have no working tree |
574 | return | 613 | return |
@@ -584,14 +623,14 @@ uncommitted changes are present' % project.relpath | |||
584 | if project.worktree: | 623 | if project.worktree: |
585 | project.Sync_LocalHalf(syncbuf) | 624 | project.Sync_LocalHalf(syncbuf) |
586 | pm.end() | 625 | pm.end() |
587 | print >>sys.stderr | 626 | print(file=sys.stderr) |
588 | if not syncbuf.Finish(): | 627 | if not syncbuf.Finish(): |
589 | sys.exit(1) | 628 | sys.exit(1) |
590 | 629 | ||
591 | # If there's a notice that's supposed to print at the end of the sync, print | 630 | # If there's a notice that's supposed to print at the end of the sync, print |
592 | # it now... | 631 | # it now... |
593 | if self.manifest.notice: | 632 | if self.manifest.notice: |
594 | print self.manifest.notice | 633 | print(self.manifest.notice) |
595 | 634 | ||
596 | def _PostRepoUpgrade(manifest, quiet=False): | 635 | def _PostRepoUpgrade(manifest, quiet=False): |
597 | wrapper = WrapperModule() | 636 | wrapper = WrapperModule() |
@@ -603,27 +642,28 @@ def _PostRepoUpgrade(manifest, quiet=False): | |||
603 | 642 | ||
604 | def _PostRepoFetch(rp, no_repo_verify=False, verbose=False): | 643 | def _PostRepoFetch(rp, no_repo_verify=False, verbose=False): |
605 | if rp.HasChanges: | 644 | if rp.HasChanges: |
606 | print >>sys.stderr, 'info: A new version of repo is available' | 645 | print('info: A new version of repo is available', file=sys.stderr) |
607 | print >>sys.stderr, '' | 646 | print(file=sys.stderr) |
608 | if no_repo_verify or _VerifyTag(rp): | 647 | if no_repo_verify or _VerifyTag(rp): |
609 | syncbuf = SyncBuffer(rp.config) | 648 | syncbuf = SyncBuffer(rp.config) |
610 | rp.Sync_LocalHalf(syncbuf) | 649 | rp.Sync_LocalHalf(syncbuf) |
611 | if not syncbuf.Finish(): | 650 | if not syncbuf.Finish(): |
612 | sys.exit(1) | 651 | sys.exit(1) |
613 | print >>sys.stderr, 'info: Restarting repo with latest version' | 652 | print('info: Restarting repo with latest version', file=sys.stderr) |
614 | raise RepoChangedException(['--repo-upgraded']) | 653 | raise RepoChangedException(['--repo-upgraded']) |
615 | else: | 654 | else: |
616 | print >>sys.stderr, 'warning: Skipped upgrade to unverified version' | 655 | print('warning: Skipped upgrade to unverified version', file=sys.stderr) |
617 | else: | 656 | else: |
618 | if verbose: | 657 | if verbose: |
619 | print >>sys.stderr, 'repo version %s is current' % rp.work_git.describe(HEAD) | 658 | print('repo version %s is current' % rp.work_git.describe(HEAD), |
659 | file=sys.stderr) | ||
620 | 660 | ||
621 | def _VerifyTag(project): | 661 | def _VerifyTag(project): |
622 | gpg_dir = os.path.expanduser('~/.repoconfig/gnupg') | 662 | gpg_dir = os.path.expanduser('~/.repoconfig/gnupg') |
623 | if not os.path.exists(gpg_dir): | 663 | if not os.path.exists(gpg_dir): |
624 | print >>sys.stderr,\ | 664 | print('warning: GnuPG was not available during last "repo init"\n' |
625 | """warning: GnuPG was not available during last "repo init" | 665 | 'warning: Cannot automatically authenticate repo."""', |
626 | warning: Cannot automatically authenticate repo.""" | 666 | file=sys.stderr) |
627 | return True | 667 | return True |
628 | 668 | ||
629 | try: | 669 | try: |
@@ -637,10 +677,9 @@ warning: Cannot automatically authenticate repo.""" | |||
637 | if rev.startswith(R_HEADS): | 677 | if rev.startswith(R_HEADS): |
638 | rev = rev[len(R_HEADS):] | 678 | rev = rev[len(R_HEADS):] |
639 | 679 | ||
640 | print >>sys.stderr | 680 | print(file=sys.stderr) |
641 | print >>sys.stderr,\ | 681 | print("warning: project '%s' branch '%s' is not signed" |
642 | "warning: project '%s' branch '%s' is not signed" \ | 682 | % (project.name, rev), file=sys.stderr) |
643 | % (project.name, rev) | ||
644 | return False | 683 | return False |
645 | 684 | ||
646 | env = os.environ.copy() | 685 | env = os.environ.copy() |
@@ -659,10 +698,10 @@ warning: Cannot automatically authenticate repo.""" | |||
659 | proc.stderr.close() | 698 | proc.stderr.close() |
660 | 699 | ||
661 | if proc.wait() != 0: | 700 | if proc.wait() != 0: |
662 | print >>sys.stderr | 701 | print(file=sys.stderr) |
663 | print >>sys.stderr, out | 702 | print(out, file=sys.stderr) |
664 | print >>sys.stderr, err | 703 | print(err, file=sys.stderr) |
665 | print >>sys.stderr | 704 | print(file=sys.stderr) |
666 | return False | 705 | return False |
667 | return True | 706 | return True |
668 | 707 | ||
@@ -696,7 +735,7 @@ class _FetchTimes(object): | |||
696 | try: | 735 | try: |
697 | try: | 736 | try: |
698 | self._times = pickle.load(f) | 737 | self._times = pickle.load(f) |
699 | except: | 738 | except IOError: |
700 | try: | 739 | try: |
701 | os.remove(self._path) | 740 | os.remove(self._path) |
702 | except OSError: | 741 | except OSError: |
diff --git a/subcmds/upload.py b/subcmds/upload.py index 84a5e440..e314032a 100644 --- a/subcmds/upload.py +++ b/subcmds/upload.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import copy | 17 | import copy |
17 | import re | 18 | import re |
18 | import sys | 19 | import sys |
@@ -26,16 +27,18 @@ UNUSUAL_COMMIT_THRESHOLD = 5 | |||
26 | 27 | ||
27 | def _ConfirmManyUploads(multiple_branches=False): | 28 | def _ConfirmManyUploads(multiple_branches=False): |
28 | if multiple_branches: | 29 | if multiple_branches: |
29 | print "ATTENTION: One or more branches has an unusually high number of commits." | 30 | print('ATTENTION: One or more branches has an unusually high number' |
31 | 'of commits.') | ||
30 | else: | 32 | else: |
31 | print "ATTENTION: You are uploading an unusually high number of commits." | 33 | print('ATTENTION: You are uploading an unusually high number of commits.') |
32 | print "YOU PROBABLY DO NOT MEAN TO DO THIS. (Did you rebase across branches?)" | 34 | print('YOU PROBABLY DO NOT MEAN TO DO THIS. (Did you rebase across' |
35 | 'branches?)') | ||
33 | answer = raw_input("If you are sure you intend to do this, type 'yes': ").strip() | 36 | answer = raw_input("If you are sure you intend to do this, type 'yes': ").strip() |
34 | return answer == "yes" | 37 | return answer == "yes" |
35 | 38 | ||
36 | def _die(fmt, *args): | 39 | def _die(fmt, *args): |
37 | msg = fmt % args | 40 | msg = fmt % args |
38 | print >>sys.stderr, 'error: %s' % msg | 41 | print('error: %s' % msg, file=sys.stderr) |
39 | sys.exit(1) | 42 | sys.exit(1) |
40 | 43 | ||
41 | def _SplitEmails(values): | 44 | def _SplitEmails(values): |
@@ -47,7 +50,7 @@ def _SplitEmails(values): | |||
47 | class Upload(InteractiveCommand): | 50 | class Upload(InteractiveCommand): |
48 | common = True | 51 | common = True |
49 | helpSummary = "Upload changes for code review" | 52 | helpSummary = "Upload changes for code review" |
50 | helpUsage=""" | 53 | helpUsage = """ |
51 | %prog [--re --cc] [<project>]... | 54 | %prog [--re --cc] [<project>]... |
52 | """ | 55 | """ |
53 | helpDescription = """ | 56 | helpDescription = """ |
@@ -176,18 +179,18 @@ Gerrit Code Review: http://code.google.com/p/gerrit/ | |||
176 | date = branch.date | 179 | date = branch.date |
177 | commit_list = branch.commits | 180 | commit_list = branch.commits |
178 | 181 | ||
179 | print 'Upload project %s/ to remote branch %s:' % (project.relpath, project.revisionExpr) | 182 | print('Upload project %s/ to remote branch %s:' % (project.relpath, project.revisionExpr)) |
180 | print ' branch %s (%2d commit%s, %s):' % ( | 183 | print(' branch %s (%2d commit%s, %s):' % ( |
181 | name, | 184 | name, |
182 | len(commit_list), | 185 | len(commit_list), |
183 | len(commit_list) != 1 and 's' or '', | 186 | len(commit_list) != 1 and 's' or '', |
184 | date) | 187 | date)) |
185 | for commit in commit_list: | 188 | for commit in commit_list: |
186 | print ' %s' % commit | 189 | print(' %s' % commit) |
187 | 190 | ||
188 | sys.stdout.write('to %s (y/N)? ' % remote.review) | 191 | sys.stdout.write('to %s (y/N)? ' % remote.review) |
189 | answer = sys.stdin.readline().strip() | 192 | answer = sys.stdin.readline().strip().lower() |
190 | answer = answer in ('y', 'Y', 'yes', '1', 'true', 't') | 193 | answer = answer in ('y', 'yes', '1', 'true', 't') |
191 | 194 | ||
192 | if answer: | 195 | if answer: |
193 | if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD: | 196 | if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD: |
@@ -297,7 +300,7 @@ Gerrit Code Review: http://code.google.com/p/gerrit/ | |||
297 | try: | 300 | try: |
298 | # refs/changes/XYZ/N --> XYZ | 301 | # refs/changes/XYZ/N --> XYZ |
299 | return refs.get(last_pub).split('/')[-2] | 302 | return refs.get(last_pub).split('/')[-2] |
300 | except: | 303 | except (AttributeError, IndexError): |
301 | return "" | 304 | return "" |
302 | 305 | ||
303 | def _UploadAndReport(self, opt, todo, original_people): | 306 | def _UploadAndReport(self, opt, todo, original_people): |
@@ -309,23 +312,23 @@ Gerrit Code Review: http://code.google.com/p/gerrit/ | |||
309 | 312 | ||
310 | # Check if there are local changes that may have been forgotten | 313 | # Check if there are local changes that may have been forgotten |
311 | if branch.project.HasChanges(): | 314 | if branch.project.HasChanges(): |
312 | key = 'review.%s.autoupload' % branch.project.remote.review | 315 | key = 'review.%s.autoupload' % branch.project.remote.review |
313 | answer = branch.project.config.GetBoolean(key) | 316 | answer = branch.project.config.GetBoolean(key) |
314 | 317 | ||
315 | # if they want to auto upload, let's not ask because it could be automated | 318 | # if they want to auto upload, let's not ask because it could be automated |
316 | if answer is None: | 319 | if answer is None: |
317 | sys.stdout.write('Uncommitted changes in ' + branch.project.name + ' (did you forget to amend?). Continue uploading? (y/N) ') | 320 | sys.stdout.write('Uncommitted changes in ' + branch.project.name + ' (did you forget to amend?). Continue uploading? (y/N) ') |
318 | a = sys.stdin.readline().strip().lower() | 321 | a = sys.stdin.readline().strip().lower() |
319 | if a not in ('y', 'yes', 't', 'true', 'on'): | 322 | if a not in ('y', 'yes', 't', 'true', 'on'): |
320 | print >>sys.stderr, "skipping upload" | 323 | print("skipping upload", file=sys.stderr) |
321 | branch.uploaded = False | 324 | branch.uploaded = False |
322 | branch.error = 'User aborted' | 325 | branch.error = 'User aborted' |
323 | continue | 326 | continue |
324 | 327 | ||
325 | # Check if topic branches should be sent to the server during upload | 328 | # Check if topic branches should be sent to the server during upload |
326 | if opt.auto_topic is not True: | 329 | if opt.auto_topic is not True: |
327 | key = 'review.%s.uploadtopic' % branch.project.remote.review | 330 | key = 'review.%s.uploadtopic' % branch.project.remote.review |
328 | opt.auto_topic = branch.project.config.GetBoolean(key) | 331 | opt.auto_topic = branch.project.config.GetBoolean(key) |
329 | 332 | ||
330 | branch.UploadForReview(people, auto_topic=opt.auto_topic, draft=opt.draft) | 333 | branch.UploadForReview(people, auto_topic=opt.auto_topic, draft=opt.draft) |
331 | branch.uploaded = True | 334 | branch.uploaded = True |
@@ -334,8 +337,8 @@ Gerrit Code Review: http://code.google.com/p/gerrit/ | |||
334 | branch.uploaded = False | 337 | branch.uploaded = False |
335 | have_errors = True | 338 | have_errors = True |
336 | 339 | ||
337 | print >>sys.stderr, '' | 340 | print(file=sys.stderr) |
338 | print >>sys.stderr, '----------------------------------------------------------------------' | 341 | print('----------------------------------------------------------------------', file=sys.stderr) |
339 | 342 | ||
340 | if have_errors: | 343 | if have_errors: |
341 | for branch in todo: | 344 | for branch in todo: |
@@ -344,17 +347,19 @@ Gerrit Code Review: http://code.google.com/p/gerrit/ | |||
344 | fmt = ' (%s)' | 347 | fmt = ' (%s)' |
345 | else: | 348 | else: |
346 | fmt = '\n (%s)' | 349 | fmt = '\n (%s)' |
347 | print >>sys.stderr, ('[FAILED] %-15s %-15s' + fmt) % ( | 350 | print(('[FAILED] %-15s %-15s' + fmt) % ( |
348 | branch.project.relpath + '/', \ | 351 | branch.project.relpath + '/', \ |
349 | branch.name, \ | 352 | branch.name, \ |
350 | str(branch.error)) | 353 | str(branch.error)), |
351 | print >>sys.stderr, '' | 354 | file=sys.stderr) |
355 | print() | ||
352 | 356 | ||
353 | for branch in todo: | 357 | for branch in todo: |
354 | if branch.uploaded: | 358 | if branch.uploaded: |
355 | print >>sys.stderr, '[OK ] %-15s %s' % ( | 359 | print('[OK ] %-15s %s' % ( |
356 | branch.project.relpath + '/', | 360 | branch.project.relpath + '/', |
357 | branch.name) | 361 | branch.name), |
362 | file=sys.stderr) | ||
358 | 363 | ||
359 | if have_errors: | 364 | if have_errors: |
360 | sys.exit(1) | 365 | sys.exit(1) |
@@ -385,17 +390,17 @@ Gerrit Code Review: http://code.google.com/p/gerrit/ | |||
385 | try: | 390 | try: |
386 | hook.Run(opt.allow_all_hooks, project_list=pending_proj_names) | 391 | hook.Run(opt.allow_all_hooks, project_list=pending_proj_names) |
387 | except HookError as e: | 392 | except HookError as e: |
388 | print >>sys.stderr, "ERROR: %s" % str(e) | 393 | print("ERROR: %s" % str(e), file=sys.stderr) |
389 | return | 394 | return |
390 | 395 | ||
391 | if opt.reviewers: | 396 | if opt.reviewers: |
392 | reviewers = _SplitEmails(opt.reviewers) | 397 | reviewers = _SplitEmails(opt.reviewers) |
393 | if opt.cc: | 398 | if opt.cc: |
394 | cc = _SplitEmails(opt.cc) | 399 | cc = _SplitEmails(opt.cc) |
395 | people = (reviewers,cc) | 400 | people = (reviewers, cc) |
396 | 401 | ||
397 | if not pending: | 402 | if not pending: |
398 | print >>sys.stdout, "no branches ready for upload" | 403 | print("no branches ready for upload", file=sys.stderr) |
399 | elif len(pending) == 1 and len(pending[0][1]) == 1: | 404 | elif len(pending) == 1 and len(pending[0][1]) == 1: |
400 | self._SingleBranch(opt, pending[0][1][0], people) | 405 | self._SingleBranch(opt, pending[0][1][0], people) |
401 | else: | 406 | else: |
diff --git a/subcmds/version.py b/subcmds/version.py index 243e3676..01b7fd8c 100644 --- a/subcmds/version.py +++ b/subcmds/version.py | |||
@@ -13,6 +13,7 @@ | |||
13 | # See the License for the specific language governing permissions and | 13 | # See the License for the specific language governing permissions and |
14 | # limitations under the License. | 14 | # limitations under the License. |
15 | 15 | ||
16 | from __future__ import print_function | ||
16 | import sys | 17 | import sys |
17 | from command import Command, MirrorSafeCommand | 18 | from command import Command, MirrorSafeCommand |
18 | from git_command import git | 19 | from git_command import git |
@@ -32,12 +33,12 @@ class Version(Command, MirrorSafeCommand): | |||
32 | rp = self.manifest.repoProject | 33 | rp = self.manifest.repoProject |
33 | rem = rp.GetRemote(rp.remote.name) | 34 | rem = rp.GetRemote(rp.remote.name) |
34 | 35 | ||
35 | print 'repo version %s' % rp.work_git.describe(HEAD) | 36 | print('repo version %s' % rp.work_git.describe(HEAD)) |
36 | print ' (from %s)' % rem.url | 37 | print(' (from %s)' % rem.url) |
37 | 38 | ||
38 | if Version.wrapper_path is not None: | 39 | if Version.wrapper_path is not None: |
39 | print 'repo launcher version %s' % Version.wrapper_version | 40 | print('repo launcher version %s' % Version.wrapper_version) |
40 | print ' (from %s)' % Version.wrapper_path | 41 | print(' (from %s)' % Version.wrapper_path) |
41 | 42 | ||
42 | print git.version().strip() | 43 | print(git.version().strip()) |
43 | print 'Python %s' % sys.version | 44 | print('Python %s' % sys.version) |