summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--color.py27
-rwxr-xr-xmain.py6
-rw-r--r--project.py305
-rw-r--r--subcmds/init.py2
4 files changed, 188 insertions, 152 deletions
diff --git a/color.py b/color.py
index 7970198a..b2799286 100644
--- a/color.py
+++ b/color.py
@@ -83,15 +83,38 @@ def _Color(fg = None, bg = None, attr = None):
83 return code 83 return code
84 84
85 85
86DEFAULT = None
87
88def SetDefaultColoring(state):
89 """Set coloring behavior to |state|.
90
91 This is useful for overriding config options via the command line.
92 """
93 if state is None:
94 # Leave it alone -- return quick!
95 return
96
97 global DEFAULT
98 state = state.lower()
99 if state in ('auto',):
100 DEFAULT = state
101 elif state in ('always', 'yes', 'true', True):
102 DEFAULT = 'always'
103 elif state in ('never', 'no', 'false', False):
104 DEFAULT = 'never'
105
106
86class Coloring(object): 107class Coloring(object):
87 def __init__(self, config, section_type): 108 def __init__(self, config, section_type):
88 self._section = 'color.%s' % section_type 109 self._section = 'color.%s' % section_type
89 self._config = config 110 self._config = config
90 self._out = sys.stdout 111 self._out = sys.stdout
91 112
92 on = self._config.GetString(self._section) 113 on = DEFAULT
93 if on is None: 114 if on is None:
94 on = self._config.GetString('color.ui') 115 on = self._config.GetString(self._section)
116 if on is None:
117 on = self._config.GetString('color.ui')
95 118
96 if on == 'auto': 119 if on == 'auto':
97 if pager.active or os.isatty(1): 120 if pager.active or os.isatty(1):
diff --git a/main.py b/main.py
index 72fb39b0..47f083df 100755
--- a/main.py
+++ b/main.py
@@ -36,6 +36,7 @@ try:
36except ImportError: 36except ImportError:
37 kerberos = None 37 kerberos = None
38 38
39from color import SetDefaultColoring
39from trace import SetTrace 40from trace import SetTrace
40from git_command import git, GitCommand 41from git_command import git, GitCommand
41from git_config import init_ssh, close_ssh 42from git_config import init_ssh, close_ssh
@@ -69,6 +70,9 @@ global_options.add_option('-p', '--paginate',
69global_options.add_option('--no-pager', 70global_options.add_option('--no-pager',
70 dest='no_pager', action='store_true', 71 dest='no_pager', action='store_true',
71 help='disable the pager') 72 help='disable the pager')
73global_options.add_option('--color',
74 choices=('auto', 'always', 'never'), default=None,
75 help='control color usage: auto, always, never')
72global_options.add_option('--trace', 76global_options.add_option('--trace',
73 dest='trace', action='store_true', 77 dest='trace', action='store_true',
74 help='trace git command execution') 78 help='trace git command execution')
@@ -113,6 +117,8 @@ class _Repo(object):
113 print('fatal: invalid usage of --version', file=sys.stderr) 117 print('fatal: invalid usage of --version', file=sys.stderr)
114 return 1 118 return 1
115 119
120 SetDefaultColoring(gopts.color)
121
116 try: 122 try:
117 cmd = self.commands[name] 123 cmd = self.commands[name]
118 except KeyError: 124 except KeyError:
diff --git a/project.py b/project.py
index 01ef3149..f514af77 100644
--- a/project.py
+++ b/project.py
@@ -13,7 +13,7 @@
13# limitations under the License. 13# limitations under the License.
14 14
15from __future__ import print_function 15from __future__ import print_function
16import traceback 16import contextlib
17import errno 17import errno
18import filecmp 18import filecmp
19import os 19import os
@@ -26,6 +26,7 @@ import sys
26import tarfile 26import tarfile
27import tempfile 27import tempfile
28import time 28import time
29import traceback
29 30
30from color import Coloring 31from color import Coloring
31from git_command import GitCommand, git_require 32from git_command import GitCommand, git_require
@@ -84,7 +85,7 @@ def _ProjectHooks():
84 global _project_hook_list 85 global _project_hook_list
85 if _project_hook_list is None: 86 if _project_hook_list is None:
86 d = os.path.realpath(os.path.abspath(os.path.dirname(__file__))) 87 d = os.path.realpath(os.path.abspath(os.path.dirname(__file__)))
87 d = os.path.join(d , 'hooks') 88 d = os.path.join(d, 'hooks')
88 _project_hook_list = [os.path.join(d, x) for x in os.listdir(d)] 89 _project_hook_list = [os.path.join(d, x) for x in os.listdir(d)]
89 return _project_hook_list 90 return _project_hook_list
90 91
@@ -182,28 +183,28 @@ class ReviewableBranch(object):
182class StatusColoring(Coloring): 183class StatusColoring(Coloring):
183 def __init__(self, config): 184 def __init__(self, config):
184 Coloring.__init__(self, config, 'status') 185 Coloring.__init__(self, config, 'status')
185 self.project = self.printer('header', attr = 'bold') 186 self.project = self.printer('header', attr='bold')
186 self.branch = self.printer('header', attr = 'bold') 187 self.branch = self.printer('header', attr='bold')
187 self.nobranch = self.printer('nobranch', fg = 'red') 188 self.nobranch = self.printer('nobranch', fg='red')
188 self.important = self.printer('important', fg = 'red') 189 self.important = self.printer('important', fg='red')
189 190
190 self.added = self.printer('added', fg = 'green') 191 self.added = self.printer('added', fg='green')
191 self.changed = self.printer('changed', fg = 'red') 192 self.changed = self.printer('changed', fg='red')
192 self.untracked = self.printer('untracked', fg = 'red') 193 self.untracked = self.printer('untracked', fg='red')
193 194
194 195
195class DiffColoring(Coloring): 196class DiffColoring(Coloring):
196 def __init__(self, config): 197 def __init__(self, config):
197 Coloring.__init__(self, config, 'diff') 198 Coloring.__init__(self, config, 'diff')
198 self.project = self.printer('header', attr = 'bold') 199 self.project = self.printer('header', attr='bold')
199 200
200class _Annotation: 201class _Annotation(object):
201 def __init__(self, name, value, keep): 202 def __init__(self, name, value, keep):
202 self.name = name 203 self.name = name
203 self.value = value 204 self.value = value
204 self.keep = keep 205 self.keep = keep
205 206
206class _CopyFile: 207class _CopyFile(object):
207 def __init__(self, src, dest, abssrc, absdest): 208 def __init__(self, src, dest, abssrc, absdest):
208 self.src = src 209 self.src = src
209 self.dest = dest 210 self.dest = dest
@@ -231,7 +232,7 @@ class _CopyFile:
231 except IOError: 232 except IOError:
232 _error('Cannot copy file %s to %s', src, dest) 233 _error('Cannot copy file %s to %s', src, dest)
233 234
234class _LinkFile: 235class _LinkFile(object):
235 def __init__(self, src, dest, abssrc, absdest): 236 def __init__(self, src, dest, abssrc, absdest):
236 self.src = src 237 self.src = src
237 self.dest = dest 238 self.dest = dest
@@ -258,9 +259,9 @@ class _LinkFile:
258class RemoteSpec(object): 259class RemoteSpec(object):
259 def __init__(self, 260 def __init__(self,
260 name, 261 name,
261 url = None, 262 url=None,
262 review = None, 263 review=None,
263 revision = None): 264 revision=None):
264 self.name = name 265 self.name = name
265 self.url = url 266 self.url = url
266 self.review = review 267 self.review = review
@@ -520,15 +521,15 @@ class Project(object):
520 relpath, 521 relpath,
521 revisionExpr, 522 revisionExpr,
522 revisionId, 523 revisionId,
523 rebase = True, 524 rebase=True,
524 groups = None, 525 groups=None,
525 sync_c = False, 526 sync_c=False,
526 sync_s = False, 527 sync_s=False,
527 clone_depth = None, 528 clone_depth=None,
528 upstream = None, 529 upstream=None,
529 parent = None, 530 parent=None,
530 is_derived = False, 531 is_derived=False,
531 dest_branch = None): 532 dest_branch=None):
532 """Init a Project object. 533 """Init a Project object.
533 534
534 Args: 535 Args:
@@ -585,8 +586,8 @@ class Project(object):
585 self.linkfiles = [] 586 self.linkfiles = []
586 self.annotations = [] 587 self.annotations = []
587 self.config = GitConfig.ForRepository( 588 self.config = GitConfig.ForRepository(
588 gitdir = self.gitdir, 589 gitdir=self.gitdir,
589 defaults = self.manifest.globalConfig) 590 defaults=self.manifest.globalConfig)
590 591
591 if self.worktree: 592 if self.worktree:
592 self.work_git = self._GitGetByExec(self, bare=False, gitdir=gitdir) 593 self.work_git = self._GitGetByExec(self, bare=False, gitdir=gitdir)
@@ -879,8 +880,8 @@ class Project(object):
879 cmd.append('--') 880 cmd.append('--')
880 p = GitCommand(self, 881 p = GitCommand(self,
881 cmd, 882 cmd,
882 capture_stdout = True, 883 capture_stdout=True,
883 capture_stderr = True) 884 capture_stderr=True)
884 has_diff = False 885 has_diff = False
885 for line in p.process.stdout: 886 for line in p.process.stdout:
886 if not has_diff: 887 if not has_diff:
@@ -965,7 +966,7 @@ class Project(object):
965 return None 966 return None
966 967
967 def UploadForReview(self, branch=None, 968 def UploadForReview(self, branch=None,
968 people=([],[]), 969 people=([], []),
969 auto_topic=False, 970 auto_topic=False,
970 draft=False, 971 draft=False,
971 dest_branch=None): 972 dest_branch=None):
@@ -1026,13 +1027,13 @@ class Project(object):
1026 ref_spec = ref_spec + '%' + ','.join(rp) 1027 ref_spec = ref_spec + '%' + ','.join(rp)
1027 cmd.append(ref_spec) 1028 cmd.append(ref_spec)
1028 1029
1029 if GitCommand(self, cmd, bare = True).Wait() != 0: 1030 if GitCommand(self, cmd, bare=True).Wait() != 0:
1030 raise UploadError('Upload failed') 1031 raise UploadError('Upload failed')
1031 1032
1032 msg = "posted to %s for %s" % (branch.remote.review, dest_branch) 1033 msg = "posted to %s for %s" % (branch.remote.review, dest_branch)
1033 self.bare_git.UpdateRef(R_PUB + branch.name, 1034 self.bare_git.UpdateRef(R_PUB + branch.name,
1034 R_HEADS + branch.name, 1035 R_HEADS + branch.name,
1035 message = msg) 1036 message=msg)
1036 1037
1037 1038
1038## Sync ## 1039## Sync ##
@@ -1133,7 +1134,7 @@ class Project(object):
1133 and not self._RemoteFetch(initial=is_new, quiet=quiet, alt_dir=alt_dir, 1134 and not self._RemoteFetch(initial=is_new, quiet=quiet, alt_dir=alt_dir,
1134 current_branch_only=current_branch_only, 1135 current_branch_only=current_branch_only,
1135 no_tags=no_tags)): 1136 no_tags=no_tags)):
1136 return False 1137 return False
1137 1138
1138 if self.worktree: 1139 if self.worktree:
1139 self._InitMRef() 1140 self._InitMRef()
@@ -1329,7 +1330,7 @@ class Project(object):
1329 1330
1330 if cnt_mine > 0 and self.rebase: 1331 if cnt_mine > 0 and self.rebase:
1331 def _dorebase(): 1332 def _dorebase():
1332 self._Rebase(upstream = '%s^1' % last_mine, onto = revid) 1333 self._Rebase(upstream='%s^1' % last_mine, onto=revid)
1333 self._CopyAndLinkFiles() 1334 self._CopyAndLinkFiles()
1334 syncbuf.later2(self, _dorebase) 1335 syncbuf.later2(self, _dorebase)
1335 elif local_changes: 1336 elif local_changes:
@@ -1384,11 +1385,11 @@ class Project(object):
1384 return True 1385 return True
1385 1386
1386 all_refs = self.bare_ref.all 1387 all_refs = self.bare_ref.all
1387 if (R_HEADS + name) in all_refs: 1388 if R_HEADS + name in all_refs:
1388 return GitCommand(self, 1389 return GitCommand(self,
1389 ['checkout', name, '--'], 1390 ['checkout', name, '--'],
1390 capture_stdout = True, 1391 capture_stdout=True,
1391 capture_stderr = True).Wait() == 0 1392 capture_stderr=True).Wait() == 0
1392 1393
1393 branch = self.GetBranch(name) 1394 branch = self.GetBranch(name)
1394 branch.remote = self.GetRemote(self.remote.name) 1395 branch.remote = self.GetRemote(self.remote.name)
@@ -1415,8 +1416,8 @@ class Project(object):
1415 1416
1416 if GitCommand(self, 1417 if GitCommand(self,
1417 ['checkout', '-b', branch.name, revid], 1418 ['checkout', '-b', branch.name, revid],
1418 capture_stdout = True, 1419 capture_stdout=True,
1419 capture_stderr = True).Wait() == 0: 1420 capture_stderr=True).Wait() == 0:
1420 branch.Save() 1421 branch.Save()
1421 return True 1422 return True
1422 return False 1423 return False
@@ -1462,8 +1463,8 @@ class Project(object):
1462 1463
1463 return GitCommand(self, 1464 return GitCommand(self,
1464 ['checkout', name, '--'], 1465 ['checkout', name, '--'],
1465 capture_stdout = True, 1466 capture_stdout=True,
1466 capture_stderr = True).Wait() == 0 1467 capture_stderr=True).Wait() == 0
1467 1468
1468 def AbandonBranch(self, name): 1469 def AbandonBranch(self, name):
1469 """Destroy a local topic branch. 1470 """Destroy a local topic branch.
@@ -1497,8 +1498,8 @@ class Project(object):
1497 1498
1498 return GitCommand(self, 1499 return GitCommand(self,
1499 ['branch', '-D', name], 1500 ['branch', '-D', name],
1500 capture_stdout = True, 1501 capture_stdout=True,
1501 capture_stderr = True).Wait() == 0 1502 capture_stderr=True).Wait() == 0
1502 1503
1503 def PruneHeads(self): 1504 def PruneHeads(self):
1504 """Prune any topic branches already merged into upstream. 1505 """Prune any topic branches already merged into upstream.
@@ -1515,7 +1516,7 @@ class Project(object):
1515 rev = self.GetRevisionId(left) 1516 rev = self.GetRevisionId(left)
1516 if cb is not None \ 1517 if cb is not None \
1517 and not self._revlist(HEAD + '...' + rev) \ 1518 and not self._revlist(HEAD + '...' + rev) \
1518 and not self.IsDirty(consider_untracked = False): 1519 and not self.IsDirty(consider_untracked=False):
1519 self.work_git.DetachHead(HEAD) 1520 self.work_git.DetachHead(HEAD)
1520 kill.append(cb) 1521 kill.append(cb)
1521 1522
@@ -1548,7 +1549,7 @@ class Project(object):
1548 1549
1549 kept = [] 1550 kept = []
1550 for branch in kill: 1551 for branch in kill:
1551 if (R_HEADS + branch) in left: 1552 if R_HEADS + branch in left:
1552 branch = self.GetBranch(branch) 1553 branch = self.GetBranch(branch)
1553 base = branch.LocalMerge 1554 base = branch.LocalMerge
1554 if not base: 1555 if not base:
@@ -1598,8 +1599,8 @@ class Project(object):
1598 def parse_gitmodules(gitdir, rev): 1599 def parse_gitmodules(gitdir, rev):
1599 cmd = ['cat-file', 'blob', '%s:.gitmodules' % rev] 1600 cmd = ['cat-file', 'blob', '%s:.gitmodules' % rev]
1600 try: 1601 try:
1601 p = GitCommand(None, cmd, capture_stdout = True, capture_stderr = True, 1602 p = GitCommand(None, cmd, capture_stdout=True, capture_stderr=True,
1602 bare = True, gitdir = gitdir) 1603 bare=True, gitdir=gitdir)
1603 except GitError: 1604 except GitError:
1604 return [], [] 1605 return [], []
1605 if p.Wait() != 0: 1606 if p.Wait() != 0:
@@ -1611,8 +1612,8 @@ class Project(object):
1611 os.write(fd, p.stdout) 1612 os.write(fd, p.stdout)
1612 os.close(fd) 1613 os.close(fd)
1613 cmd = ['config', '--file', temp_gitmodules_path, '--list'] 1614 cmd = ['config', '--file', temp_gitmodules_path, '--list']
1614 p = GitCommand(None, cmd, capture_stdout = True, capture_stderr = True, 1615 p = GitCommand(None, cmd, capture_stdout=True, capture_stderr=True,
1615 bare = True, gitdir = gitdir) 1616 bare=True, gitdir=gitdir)
1616 if p.Wait() != 0: 1617 if p.Wait() != 0:
1617 return [], [] 1618 return [], []
1618 gitmodules_lines = p.stdout.split('\n') 1619 gitmodules_lines = p.stdout.split('\n')
@@ -1645,8 +1646,8 @@ class Project(object):
1645 cmd = ['ls-tree', rev, '--'] 1646 cmd = ['ls-tree', rev, '--']
1646 cmd.extend(paths) 1647 cmd.extend(paths)
1647 try: 1648 try:
1648 p = GitCommand(None, cmd, capture_stdout = True, capture_stderr = True, 1649 p = GitCommand(None, cmd, capture_stdout=True, capture_stderr=True,
1649 bare = True, gitdir = gitdir) 1650 bare=True, gitdir=gitdir)
1650 except GitError: 1651 except GitError:
1651 return [] 1652 return []
1652 if p.Wait() != 0: 1653 if p.Wait() != 0:
@@ -1681,24 +1682,24 @@ class Project(object):
1681 continue 1682 continue
1682 1683
1683 remote = RemoteSpec(self.remote.name, 1684 remote = RemoteSpec(self.remote.name,
1684 url = url, 1685 url=url,
1685 review = self.remote.review, 1686 review=self.remote.review,
1686 revision = self.remote.revision) 1687 revision=self.remote.revision)
1687 subproject = Project(manifest = self.manifest, 1688 subproject = Project(manifest=self.manifest,
1688 name = name, 1689 name=name,
1689 remote = remote, 1690 remote=remote,
1690 gitdir = gitdir, 1691 gitdir=gitdir,
1691 objdir = objdir, 1692 objdir=objdir,
1692 worktree = worktree, 1693 worktree=worktree,
1693 relpath = relpath, 1694 relpath=relpath,
1694 revisionExpr = self.revisionExpr, 1695 revisionExpr=self.revisionExpr,
1695 revisionId = rev, 1696 revisionId=rev,
1696 rebase = self.rebase, 1697 rebase=self.rebase,
1697 groups = self.groups, 1698 groups=self.groups,
1698 sync_c = self.sync_c, 1699 sync_c=self.sync_c,
1699 sync_s = self.sync_s, 1700 sync_s=self.sync_s,
1700 parent = self, 1701 parent=self,
1701 is_derived = True) 1702 is_derived=True)
1702 result.append(subproject) 1703 result.append(subproject)
1703 result.extend(subproject.GetDerivedSubprojects()) 1704 result.extend(subproject.GetDerivedSubprojects())
1704 return result 1705 return result
@@ -1854,9 +1855,9 @@ class Project(object):
1854 GitCommand(self, ['fetch', '--unshallow', name] + shallowfetch.split(), 1855 GitCommand(self, ['fetch', '--unshallow', name] + shallowfetch.split(),
1855 bare=True, ssh_proxy=ssh_proxy).Wait() 1856 bare=True, ssh_proxy=ssh_proxy).Wait()
1856 if depth: 1857 if depth:
1857 self.config.SetString('repo.shallowfetch', ' '.join(spec)) 1858 self.config.SetString('repo.shallowfetch', ' '.join(spec))
1858 else: 1859 else:
1859 self.config.SetString('repo.shallowfetch', None) 1860 self.config.SetString('repo.shallowfetch', None)
1860 1861
1861 ok = False 1862 ok = False
1862 for _i in range(2): 1863 for _i in range(2):
@@ -1946,34 +1947,34 @@ class Project(object):
1946 os.remove(tmpPath) 1947 os.remove(tmpPath)
1947 if 'http_proxy' in os.environ and 'darwin' == sys.platform: 1948 if 'http_proxy' in os.environ and 'darwin' == sys.platform:
1948 cmd += ['--proxy', os.environ['http_proxy']] 1949 cmd += ['--proxy', os.environ['http_proxy']]
1949 cookiefile = self._GetBundleCookieFile(srcUrl) 1950 with self._GetBundleCookieFile(srcUrl, quiet) as cookiefile:
1950 if cookiefile: 1951 if cookiefile:
1951 cmd += ['--cookie', cookiefile] 1952 cmd += ['--cookie', cookiefile, '--cookie-jar', cookiefile]
1952 if srcUrl.startswith('persistent-'): 1953 if srcUrl.startswith('persistent-'):
1953 srcUrl = srcUrl[len('persistent-'):] 1954 srcUrl = srcUrl[len('persistent-'):]
1954 cmd += [srcUrl] 1955 cmd += [srcUrl]
1955 1956
1956 if IsTrace(): 1957 if IsTrace():
1957 Trace('%s', ' '.join(cmd)) 1958 Trace('%s', ' '.join(cmd))
1958 try: 1959 try:
1959 proc = subprocess.Popen(cmd) 1960 proc = subprocess.Popen(cmd)
1960 except OSError: 1961 except OSError:
1961 return False 1962 return False
1962 1963
1963 curlret = proc.wait() 1964 curlret = proc.wait()
1964 1965
1965 if curlret == 22: 1966 if curlret == 22:
1966 # From curl man page: 1967 # From curl man page:
1967 # 22: HTTP page not retrieved. The requested url was not found or 1968 # 22: HTTP page not retrieved. The requested url was not found or
1968 # returned another error with the HTTP error code being 400 or above. 1969 # returned another error with the HTTP error code being 400 or above.
1969 # This return code only appears if -f, --fail is used. 1970 # This return code only appears if -f, --fail is used.
1970 if not quiet: 1971 if not quiet:
1971 print("Server does not provide clone.bundle; ignoring.", 1972 print("Server does not provide clone.bundle; ignoring.",
1972 file=sys.stderr) 1973 file=sys.stderr)
1973 return False 1974 return False
1974 1975
1975 if os.path.exists(tmpPath): 1976 if os.path.exists(tmpPath):
1976 if curlret == 0 and self._IsValidBundle(tmpPath): 1977 if curlret == 0 and self._IsValidBundle(tmpPath, quiet):
1977 os.rename(tmpPath, dstPath) 1978 os.rename(tmpPath, dstPath)
1978 return True 1979 return True
1979 else: 1980 else:
@@ -1982,45 +1983,51 @@ class Project(object):
1982 else: 1983 else:
1983 return False 1984 return False
1984 1985
1985 def _IsValidBundle(self, path): 1986 def _IsValidBundle(self, path, quiet):
1986 try: 1987 try:
1987 with open(path) as f: 1988 with open(path) as f:
1988 if f.read(16) == '# v2 git bundle\n': 1989 if f.read(16) == '# v2 git bundle\n':
1989 return True 1990 return True
1990 else: 1991 else:
1991 print("Invalid clone.bundle file; ignoring.", file=sys.stderr) 1992 if not quiet:
1993 print("Invalid clone.bundle file; ignoring.", file=sys.stderr)
1992 return False 1994 return False
1993 except OSError: 1995 except OSError:
1994 return False 1996 return False
1995 1997
1996 def _GetBundleCookieFile(self, url): 1998 @contextlib.contextmanager
1999 def _GetBundleCookieFile(self, url, quiet):
1997 if url.startswith('persistent-'): 2000 if url.startswith('persistent-'):
1998 try: 2001 try:
1999 p = subprocess.Popen( 2002 p = subprocess.Popen(
2000 ['git-remote-persistent-https', '-print_config', url], 2003 ['git-remote-persistent-https', '-print_config', url],
2001 stdin=subprocess.PIPE, stdout=subprocess.PIPE, 2004 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
2002 stderr=subprocess.PIPE) 2005 stderr=subprocess.PIPE)
2003 p.stdin.close() # Tell subprocess it's ok to close. 2006 try:
2004 prefix = 'http.cookiefile=' 2007 prefix = 'http.cookiefile='
2005 cookiefile = None 2008 cookiefile = None
2006 for line in p.stdout: 2009 for line in p.stdout:
2007 line = line.strip() 2010 line = line.strip()
2008 if line.startswith(prefix): 2011 if line.startswith(prefix):
2009 cookiefile = line[len(prefix):] 2012 cookiefile = line[len(prefix):]
2010 break 2013 break
2011 if p.wait(): 2014 # Leave subprocess open, as cookie file may be transient.
2012 err_msg = p.stderr.read() 2015 if cookiefile:
2013 if ' -print_config' in err_msg: 2016 yield cookiefile
2014 pass # Persistent proxy doesn't support -print_config. 2017 return
2015 else: 2018 finally:
2016 print(err_msg, file=sys.stderr) 2019 p.stdin.close()
2017 if cookiefile: 2020 if p.wait():
2018 return cookiefile 2021 err_msg = p.stderr.read()
2022 if ' -print_config' in err_msg:
2023 pass # Persistent proxy doesn't support -print_config.
2024 elif not quiet:
2025 print(err_msg, file=sys.stderr)
2019 except OSError as e: 2026 except OSError as e:
2020 if e.errno == errno.ENOENT: 2027 if e.errno == errno.ENOENT:
2021 pass # No persistent proxy. 2028 pass # No persistent proxy.
2022 raise 2029 raise
2023 return GitConfig.ForUser().GetString('http.cookiefile') 2030 yield GitConfig.ForUser().GetString('http.cookiefile')
2024 2031
2025 def _Checkout(self, rev, quiet=False): 2032 def _Checkout(self, rev, quiet=False):
2026 cmd = ['checkout'] 2033 cmd = ['checkout']
@@ -2032,7 +2039,7 @@ class Project(object):
2032 if self._allrefs: 2039 if self._allrefs:
2033 raise GitError('%s checkout %s ' % (self.name, rev)) 2040 raise GitError('%s checkout %s ' % (self.name, rev))
2034 2041
2035 def _CherryPick(self, rev, quiet=False): 2042 def _CherryPick(self, rev):
2036 cmd = ['cherry-pick'] 2043 cmd = ['cherry-pick']
2037 cmd.append(rev) 2044 cmd.append(rev)
2038 cmd.append('--') 2045 cmd.append('--')
@@ -2040,7 +2047,7 @@ class Project(object):
2040 if self._allrefs: 2047 if self._allrefs:
2041 raise GitError('%s cherry-pick %s ' % (self.name, rev)) 2048 raise GitError('%s cherry-pick %s ' % (self.name, rev))
2042 2049
2043 def _Revert(self, rev, quiet=False): 2050 def _Revert(self, rev):
2044 cmd = ['revert'] 2051 cmd = ['revert']
2045 cmd.append('--no-edit') 2052 cmd.append('--no-edit')
2046 cmd.append(rev) 2053 cmd.append(rev)
@@ -2057,7 +2064,7 @@ class Project(object):
2057 if GitCommand(self, cmd).Wait() != 0: 2064 if GitCommand(self, cmd).Wait() != 0:
2058 raise GitError('%s reset --hard %s ' % (self.name, rev)) 2065 raise GitError('%s reset --hard %s ' % (self.name, rev))
2059 2066
2060 def _Rebase(self, upstream, onto = None): 2067 def _Rebase(self, upstream, onto=None):
2061 cmd = ['rebase'] 2068 cmd = ['rebase']
2062 if onto is not None: 2069 if onto is not None:
2063 cmd.extend(['--onto', onto]) 2070 cmd.extend(['--onto', onto])
@@ -2112,7 +2119,7 @@ class Project(object):
2112 2119
2113 m = self.manifest.manifestProject.config 2120 m = self.manifest.manifestProject.config
2114 for key in ['user.name', 'user.email']: 2121 for key in ['user.name', 'user.email']:
2115 if m.Has(key, include_defaults = False): 2122 if m.Has(key, include_defaults=False):
2116 self.config.SetString(key, m.GetString(key)) 2123 self.config.SetString(key, m.GetString(key))
2117 if self.manifest.IsMirror: 2124 if self.manifest.IsMirror:
2118 self.config.SetString('core.bare', 'true') 2125 self.config.SetString('core.bare', 'true')
@@ -2183,7 +2190,7 @@ class Project(object):
2183 if cur != '' or self.bare_ref.get(ref) != self.revisionId: 2190 if cur != '' or self.bare_ref.get(ref) != self.revisionId:
2184 msg = 'manifest set to %s' % self.revisionId 2191 msg = 'manifest set to %s' % self.revisionId
2185 dst = self.revisionId + '^0' 2192 dst = self.revisionId + '^0'
2186 self.bare_git.UpdateRef(ref, dst, message = msg, detach = True) 2193 self.bare_git.UpdateRef(ref, dst, message=msg, detach=True)
2187 else: 2194 else:
2188 remote = self.GetRemote(self.remote.name) 2195 remote = self.GetRemote(self.remote.name)
2189 dst = remote.ToLocal(self.revisionExpr) 2196 dst = remote.ToLocal(self.revisionExpr)
@@ -2327,10 +2334,10 @@ class Project(object):
2327 '-z', 2334 '-z',
2328 '--others', 2335 '--others',
2329 '--exclude-standard'], 2336 '--exclude-standard'],
2330 bare = False, 2337 bare=False,
2331 gitdir=self._gitdir, 2338 gitdir=self._gitdir,
2332 capture_stdout = True, 2339 capture_stdout=True,
2333 capture_stderr = True) 2340 capture_stderr=True)
2334 if p.Wait() == 0: 2341 if p.Wait() == 0:
2335 out = p.stdout 2342 out = p.stdout
2336 if out: 2343 if out:
@@ -2345,9 +2352,9 @@ class Project(object):
2345 p = GitCommand(self._project, 2352 p = GitCommand(self._project,
2346 cmd, 2353 cmd,
2347 gitdir=self._gitdir, 2354 gitdir=self._gitdir,
2348 bare = False, 2355 bare=False,
2349 capture_stdout = True, 2356 capture_stdout=True,
2350 capture_stderr = True) 2357 capture_stderr=True)
2351 try: 2358 try:
2352 out = p.process.stdout.read() 2359 out = p.process.stdout.read()
2353 r = {} 2360 r = {}
@@ -2453,10 +2460,10 @@ class Project(object):
2453 cmdv.extend(args) 2460 cmdv.extend(args)
2454 p = GitCommand(self._project, 2461 p = GitCommand(self._project,
2455 cmdv, 2462 cmdv,
2456 bare = self._bare, 2463 bare=self._bare,
2457 gitdir=self._gitdir, 2464 gitdir=self._gitdir,
2458 capture_stdout = True, 2465 capture_stdout=True,
2459 capture_stderr = True) 2466 capture_stderr=True)
2460 r = [] 2467 r = []
2461 for line in p.process.stdout: 2468 for line in p.process.stdout:
2462 if line[-1] == '\n': 2469 if line[-1] == '\n':
@@ -2506,10 +2513,10 @@ class Project(object):
2506 cmdv.extend(args) 2513 cmdv.extend(args)
2507 p = GitCommand(self._project, 2514 p = GitCommand(self._project,
2508 cmdv, 2515 cmdv,
2509 bare = self._bare, 2516 bare=self._bare,
2510 gitdir=self._gitdir, 2517 gitdir=self._gitdir,
2511 capture_stdout = True, 2518 capture_stdout=True,
2512 capture_stderr = True) 2519 capture_stderr=True)
2513 if p.Wait() != 0: 2520 if p.Wait() != 0:
2514 raise GitError('%s %s: %s' % ( 2521 raise GitError('%s %s: %s' % (
2515 self._project.name, 2522 self._project.name,
@@ -2574,9 +2581,9 @@ class _Later(object):
2574class _SyncColoring(Coloring): 2581class _SyncColoring(Coloring):
2575 def __init__(self, config): 2582 def __init__(self, config):
2576 Coloring.__init__(self, config, 'reposync') 2583 Coloring.__init__(self, config, 'reposync')
2577 self.project = self.printer('header', attr = 'bold') 2584 self.project = self.printer('header', attr='bold')
2578 self.info = self.printer('info') 2585 self.info = self.printer('info')
2579 self.fail = self.printer('fail', fg='red') 2586 self.fail = self.printer('fail', fg='red')
2580 2587
2581class SyncBuffer(object): 2588class SyncBuffer(object):
2582 def __init__(self, config, detach_head=False): 2589 def __init__(self, config, detach_head=False):
@@ -2638,16 +2645,16 @@ class MetaProject(Project):
2638 """ 2645 """
2639 def __init__(self, manifest, name, gitdir, worktree): 2646 def __init__(self, manifest, name, gitdir, worktree):
2640 Project.__init__(self, 2647 Project.__init__(self,
2641 manifest = manifest, 2648 manifest=manifest,
2642 name = name, 2649 name=name,
2643 gitdir = gitdir, 2650 gitdir=gitdir,
2644 objdir = gitdir, 2651 objdir=gitdir,
2645 worktree = worktree, 2652 worktree=worktree,
2646 remote = RemoteSpec('origin'), 2653 remote=RemoteSpec('origin'),
2647 relpath = '.repo/%s' % name, 2654 relpath='.repo/%s' % name,
2648 revisionExpr = 'refs/heads/master', 2655 revisionExpr='refs/heads/master',
2649 revisionId = None, 2656 revisionId=None,
2650 groups = None) 2657 groups=None)
2651 2658
2652 def PreSync(self): 2659 def PreSync(self):
2653 if self.Exists: 2660 if self.Exists:
@@ -2658,20 +2665,20 @@ class MetaProject(Project):
2658 self.revisionExpr = base 2665 self.revisionExpr = base
2659 self.revisionId = None 2666 self.revisionId = None
2660 2667
2661 def MetaBranchSwitch(self, target): 2668 def MetaBranchSwitch(self):
2662 """ Prepare MetaProject for manifest branch switch 2669 """ Prepare MetaProject for manifest branch switch
2663 """ 2670 """
2664 2671
2665 # detach and delete manifest branch, allowing a new 2672 # detach and delete manifest branch, allowing a new
2666 # branch to take over 2673 # branch to take over
2667 syncbuf = SyncBuffer(self.config, detach_head = True) 2674 syncbuf = SyncBuffer(self.config, detach_head=True)
2668 self.Sync_LocalHalf(syncbuf) 2675 self.Sync_LocalHalf(syncbuf)
2669 syncbuf.Finish() 2676 syncbuf.Finish()
2670 2677
2671 return GitCommand(self, 2678 return GitCommand(self,
2672 ['update-ref', '-d', 'refs/heads/default'], 2679 ['update-ref', '-d', 'refs/heads/default'],
2673 capture_stdout = True, 2680 capture_stdout=True,
2674 capture_stderr = True).Wait() == 0 2681 capture_stderr=True).Wait() == 0
2675 2682
2676 2683
2677 @property 2684 @property
diff --git a/subcmds/init.py b/subcmds/init.py
index b1fcb69c..b73de71c 100644
--- a/subcmds/init.py
+++ b/subcmds/init.py
@@ -233,7 +233,7 @@ to update the working directory files.
233 sys.exit(1) 233 sys.exit(1)
234 234
235 if opt.manifest_branch: 235 if opt.manifest_branch:
236 m.MetaBranchSwitch(opt.manifest_branch) 236 m.MetaBranchSwitch()
237 237
238 syncbuf = SyncBuffer(m.config) 238 syncbuf = SyncBuffer(m.config)
239 m.Sync_LocalHalf(syncbuf) 239 m.Sync_LocalHalf(syncbuf)