Commit cca15f81 authored by Matthias Putz's avatar Matthias Putz

adapted style to PEP8 style guide

parent 294579e8
......@@ -18,148 +18,155 @@ import sys
import pager
COLORS = {None :-1,
'normal' :-1,
'black' : 0,
'red' : 1,
'green' : 2,
'yellow' : 3,
'blue' : 4,
COLORS = {None: -1,
'normal': -1,
'black': 0,
'red': 1,
'green': 2,
'yellow': 3,
'blue': 4,
'magenta': 5,
'cyan' : 6,
'white' : 7}
ATTRS = {None :-1,
'bold' : 1,
'dim' : 2,
'ul' : 4,
'blink' : 5,
'cyan': 6,
'white': 7}
ATTRS = {None: -1,
'bold': 1,
'dim': 2,
'ul': 4,
'blink': 5,
'reverse': 7}
RESET = "\033[m" # pylint: disable=W1401
# backslash is not anomalous
# backslash is not anomalous
def is_color(s):
return s in COLORS
return s in COLORS
def is_attr(s):
return s in ATTRS
def _Color(fg = None, bg = None, attr = None):
fg = COLORS[fg]
bg = COLORS[bg]
attr = ATTRS[attr]
if attr >= 0 or fg >= 0 or bg >= 0:
need_sep = False
code = "\033[" #pylint: disable=W1401
if attr >= 0:
code += chr(ord('0') + attr)
need_sep = True
if fg >= 0:
if need_sep:
code += ';'
need_sep = True
if fg < 8:
code += '3%c' % (ord('0') + fg)
else:
code += '38;5;%d' % fg
if bg >= 0:
if need_sep:
code += ';'
need_sep = True
if bg < 8:
code += '4%c' % (ord('0') + bg)
else:
code += '48;5;%d' % bg
code += 'm'
else:
code = ''
return code
return s in ATTRS
def _Color(fg=None, bg=None, attr=None):
fg = COLORS[fg]
bg = COLORS[bg]
attr = ATTRS[attr]
if attr >= 0 or fg >= 0 or bg >= 0:
need_sep = False
code = "\033[" #pylint: disable=W1401
if attr >= 0:
code += chr(ord('0') + attr)
need_sep = True
if fg >= 0:
if need_sep:
code += ';'
need_sep = True
if fg < 8:
code += '3%c' % (ord('0') + fg)
else:
code += '38;5;%d' % fg
if bg >= 0:
if need_sep:
code += ';'
need_sep = True
if bg < 8:
code += '4%c' % (ord('0') + bg)
else:
code += '48;5;%d' % bg
code += 'm'
else:
code = ''
return code
class Coloring(object):
def __init__(self, config, section_type):
self._section = 'color.%s' % section_type
self._config = config
self._out = sys.stdout
on = self._config.GetString(self._section)
if on is None:
on = self._config.GetString('color.ui')
if on == 'auto':
if pager.active or os.isatty(1):
self._on = True
else:
self._on = False
elif on in ('true', 'always'):
self._on = True
else:
self._on = False
def redirect(self, out):
self._out = out
@property
def is_on(self):
return self._on
def write(self, fmt, *args):
self._out.write(fmt % args)
def flush(self):
self._out.flush()
def nl(self):
self._out.write('\n')
def printer(self, opt=None, fg=None, bg=None, attr=None):
s = self
c = self.colorer(opt, fg, bg, attr)
def f(fmt, *args):
s._out.write(c(fmt, *args))
return f
def colorer(self, opt=None, fg=None, bg=None, attr=None):
if self._on:
c = self._parse(opt, fg, bg, attr)
def f(fmt, *args):
output = fmt % args
return ''.join([c, output, RESET])
return f
else:
def f(fmt, *args):
return fmt % args
return f
def _parse(self, opt, fg, bg, attr):
if not opt:
return _Color(fg, bg, attr)
v = self._config.GetString('%s.%s' % (self._section, opt))
if v is None:
return _Color(fg, bg, attr)
v = v.strip().lower()
if v == "reset":
return RESET
elif v == '':
return _Color(fg, bg, attr)
have_fg = False
for a in v.split(' '):
if is_color(a):
if have_fg:
bg = a
def __init__(self, config, section_type):
self._section = 'color.%s' % section_type
self._config = config
self._out = sys.stdout
on = self._config.GetString(self._section)
if on is None:
on = self._config.GetString('color.ui')
if on == 'auto':
if pager.active or os.isatty(1):
self._on = True
else:
self._on = False
elif on in ('true', 'always'):
self._on = True
else:
fg = a
elif is_attr(a):
attr = a
self._on = False
def redirect(self, out):
self._out = out
@property
def is_on(self):
return self._on
def write(self, fmt, *args):
self._out.write(fmt % args)
def flush(self):
self._out.flush()
return _Color(fg, bg, attr)
def nl(self):
self._out.write('\n')
def printer(self, opt=None, fg=None, bg=None, attr=None):
s = self
c = self.colorer(opt, fg, bg, attr)
def f(fmt, *args):
s._out.write(c(fmt, *args))
return f
def colorer(self, opt=None, fg=None, bg=None, attr=None):
if self._on:
c = self._parse(opt, fg, bg, attr)
def f(fmt, *args):
output = fmt % args
return ''.join([c, output, RESET])
return f
else:
def f(fmt, *args):
return fmt % args
return f
def _parse(self, opt, fg, bg, attr):
if not opt:
return _Color(fg, bg, attr)
v = self._config.GetString('%s.%s' % (self._section, opt))
if v is None:
return _Color(fg, bg, attr)
v = v.strip().lower()
if v == "reset":
return RESET
elif v == '':
return _Color(fg, bg, attr)
have_fg = False
for a in v.split(' '):
if is_color(a):
if have_fg:
bg = a
else:
fg = a
elif is_attr(a):
attr = a
return _Color(fg, bg, attr)
This diff is collapsed.
......@@ -22,89 +22,90 @@ import tempfile
from error import EditorError
class Editor(object):
"""Manages the user's preferred text editor."""
_editor = None
globalConfig = None
@classmethod
def _GetEditor(cls):
if cls._editor is None:
cls._editor = cls._SelectEditor()
return cls._editor
@classmethod
def _SelectEditor(cls):
e = os.getenv('GIT_EDITOR')
if e:
return e
if cls.globalConfig:
e = cls.globalConfig.GetString('core.editor')
if e:
return e
e = os.getenv('VISUAL')
if e:
return e
e = os.getenv('EDITOR')
if e:
return e
if os.getenv('TERM') == 'dumb':
print(
"""No editor specified in GIT_EDITOR, core.editor, VISUAL or EDITOR.
Tried to fall back to vi but terminal is dumb. Please configure at
least one of these before using this command.""", file=sys.stderr)
sys.exit(1)
return 'vi'
@classmethod
def EditString(cls, data):
"""Opens an editor to edit the given content.
Args:
data : the text to edit
Returns:
new value of edited text; None if editing did not succeed
"""
editor = cls._GetEditor()
if editor == ':':
return data
fd, path = tempfile.mkstemp()
try:
os.write(fd, data)
os.close(fd)
fd = None
if re.compile("^.*[$ \t'].*$").match(editor):
args = [editor + ' "$@"', 'sh']
shell = True
else:
args = [editor]
shell = False
args.append(path)
try:
rc = subprocess.Popen(args, shell=shell).wait()
except OSError as e:
raise EditorError('editor failed, %s: %s %s'
% (str(e), editor, path))
if rc != 0:
raise EditorError('editor failed with exit status %d: %s %s'
% (rc, editor, path))
fd2 = open(path)
try:
return fd2.read()
finally:
fd2.close()
finally:
if fd:
os.close(fd)
os.remove(path)
"""Manages the user's preferred text editor."""
_editor = None
globalConfig = None
@classmethod
def _GetEditor(cls):
if cls._editor is None:
cls._editor = cls._SelectEditor()
return cls._editor
@classmethod
def _SelectEditor(cls):
e = os.getenv('GIT_EDITOR')
if e:
return e
if cls.globalConfig:
e = cls.globalConfig.GetString('core.editor')
if e:
return e
e = os.getenv('VISUAL')
if e:
return e
e = os.getenv('EDITOR')
if e:
return e
if os.getenv('TERM') == 'dumb':
print(
"""No editor specified in GIT_EDITOR, core.editor, VISUAL or EDITOR.
Tried to fall back to vi but terminal is dumb. Please configure at
least one of these before using this command.""", file=sys.stderr)
sys.exit(1)
return 'vi'
@classmethod
def EditString(cls, data):
"""Opens an editor to edit the given content.
Args:
data : the text to edit
Returns:
new value of edited text; None if editing did not succeed
"""
editor = cls._GetEditor()
if editor == ':':
return data
fd, path = tempfile.mkstemp()
try:
os.write(fd, data)
os.close(fd)
fd = None
if re.compile("^.*[$ \t'].*$").match(editor):
args = [editor + ' "$@"', 'sh']
shell = True
else:
args = [editor]
shell = False
args.append(path)
try:
rc = subprocess.Popen(args, shell=shell).wait()
except OSError as e:
raise EditorError('editor failed, %s: %s %s'
% (str(e), editor, path))
if rc != 0:
raise EditorError('editor failed with exit status %d: %s %s'
% (rc, editor, path))
fd2 = open(path)
try:
return fd2.read()
finally:
fd2.close()
finally:
if fd:
os.close(fd)
os.remove(path)
......@@ -14,93 +14,109 @@
# limitations under the License.
class ManifestParseError(Exception):
"""Failed to parse the manifest file.
"""
"""Failed to parse the manifest file.
"""
class ManifestInvalidRevisionError(Exception):
"""The revision value in a project is incorrect.
"""
"""The revision value in a project is incorrect.
"""
class NoManifestException(Exception):
"""The required manifest does not exist.
"""
"""The required manifest does not exist.
"""
class EditorError(Exception):
"""Unspecified error from the user's text editor.
"""
def __init__(self, reason):
super(EditorError, self).__init__()
self.reason = reason
"""Unspecified error from the user's text editor.
"""
def __init__(self, reason):
super(EditorError, self).__init__()
self.reason = reason
def __str__(self):
return self.reason
def __str__(self):
return self.reason
class GitError(Exception):
"""Unspecified internal error from git.
"""
def __init__(self, command):
super(GitError, self).__init__()
self.command = command
"""Unspecified internal error from git.
"""
def __init__(self, command):
super(GitError, self).__init__()
self.command = command
def __str__(self):
return self.command
def __str__(self):
return self.command
class UploadError(Exception):
"""A bundle upload to Gerrit did not succeed.
"""
def __init__(self, reason):
super(UploadError, self).__init__()
self.reason = reason
"""A bundle upload to Gerrit did not succeed.
"""
def __init__(self, reason):
super(UploadError, self).__init__()
self.reason = reason
def __str__(self):
return self.reason
def __str__(self):
return self.reason
class DownloadError(Exception):
"""Cannot download a repository.
"""
def __init__(self, reason):
super(DownloadError, self).__init__()
self.reason = reason
"""Cannot download a repository.
"""
def __init__(self, reason):
super(DownloadError, self).__init__()
self.reason = reason
def __str__(self):
return self.reason
def __str__(self):
return self.reason
class NoSuchProjectError(Exception):
"""A specified project does not exist in the work tree.
"""
def __init__(self, name=None):
super(NoSuchProjectError, self).__init__()
self.name = name
"""A specified project does not exist in the work tree.
"""
def __init__(self, name=None):
super(NoSuchProjectError, self).__init__()
self.name = name
def __str__(self):
if self.Name is None:
return 'in current directory'
return self.name
def __str__(self):
if self.Name is None:
return 'in current directory'
return self.name
class InvalidProjectGroupsError(Exception):
"""A specified project is not suitable for the specified groups
"""
def __init__(self, name=None):
super(InvalidProjectGroupsError, self).__init__()
self.name = name
"""A specified project is not suitable for the specified groups
"""
def __init__(self, name=None):
super(InvalidProjectGroupsError, self).__init__()
self.name = name
def __str__(self):
if self.Name is None:
return 'in current directory'
return self.name
def __str__(self):
if self.Name is None:
return 'in current directory'
return self.name
class RepoChangedException(Exception):
"""Thrown if 'repo sync' results in repo updating its internal
repo or manifest repositories. In this special case we must
use exec to re-execute repo with the new code and manifest.
"""
def __init__(self, extra_args=None):
super(RepoChangedException, self).__init__()
self.extra_args = extra_args or []
"""Thrown if 'repo sync' results in repo updating its internal
repo or manifest repositories. In this special case we must
use exec to re-execute repo with the new code and manifest.
"""
def __init__(self, extra_args=None):
super(RepoChangedException, self).__init__()
self.extra_args = extra_args or []
class HookError(Exception):
"""Thrown if a 'repo-hook' could not be run.
"""Thrown if a 'repo-hook' could not be run.
The common case is that the file wasn't present when we tried to run it.
"""
The common case is that the file wasn't present when we tried to run it.
"""
This diff is collapsed.
This diff is collapsed.
......@@ -16,146 +16,146 @@
import os
from repo_trace import Trace
HEAD = 'HEAD'
HEAD = 'HEAD'
R_HEADS = 'refs/heads/'
R_TAGS = 'refs/tags/'
R_PUB = 'refs/published/'
R_M = 'refs/remotes/m/'
R_TAGS = 'refs/tags/'
R_PUB = 'refs/published/'
R_M = 'refs/remotes/m/'
class GitRefs(object):
def __init__(self, gitdir):
self._gitdir = gitdir
self._phyref = None
self._symref = None
self._mtime = {}
@property
def all(self):
self._EnsureLoaded()
return self._phyref
def get(self, name):
try:
return self.all[name]
except KeyError:
return ''
def deleted(self, name):
if self._phyref is not None:
if name in self._phyref:
del self._phyref[name]
if name in self._symref:
del self._symref[name]
if name in self._mtime:
del self._mtime[name]
def symref(self, name):
try:
self._EnsureLoaded()
return self._symref[name]
except KeyError:
return ''
def _EnsureLoaded(self):
if self._phyref is None or self._NeedUpdate():
self._LoadAll()
def _NeedUpdate(self):
Trace(': scan refs %s', self._gitdir)
for name, mtime in list(self._mtime.items()):
try:
if mtime != os.path.getmtime(os.path.join(self._gitdir, name)):
return True
except OSError:
return True
return False
def _LoadAll(self):
Trace(': load refs %s', self._gitdir)
self._phyref = {}
self._symref = {}
self._mtime = {}
self._ReadPackedRefs()
self._ReadLoose('refs/')
self._ReadLoose1(os.path.join(self._gitdir, HEAD), HEAD)
scan = self._symref
attempts = 0
while scan and attempts < 5:
scan_next = {}
for name, dest in list(scan.items()):
if dest in self._phyref:
self._phyref[name] = self._phyref[dest]
def __init__(self, gitdir):
self._gitdir = gitdir
self._phyref = None
self._symref = None
self._mtime = {}
@property
def all(self):
self._EnsureLoaded()
return self._phyref
def get(self, name):
try:
return self.all[name]
except KeyError:
return ''
def deleted(self, name):
if self._phyref is not None:
if name in self._phyref:
del self._phyref[name]
if name in self._symref:
del self._symref[name]
if name in self._mtime:
del self._mtime[name]
def symref(self, name):
try:
self._EnsureLoaded()
return self._symref[name]
except KeyError:
return ''
def _EnsureLoaded(self):
if self._phyref is None or self._NeedUpdate():
self._LoadAll()
def _NeedUpdate(self):
Trace(': scan refs %s', self._gitdir)
for name, mtime in list(self._mtime.items()):
try:
if mtime != os.path.getmtime(os.path.join(self._gitdir, name)):
return True
except OSError:
return True
return False
def _LoadAll(self):
Trace(': load refs %s', self._gitdir)
self._phyref = {}
self._symref = {}
self._mtime = {}
self._ReadPackedRefs()
self._ReadLoose('refs/')
self._ReadLoose1(os.path.join(self._gitdir, HEAD), HEAD)
scan = self._symref
attempts = 0
while scan and attempts < 5:
scan_next = {}
for name, dest in list(scan.items()):
if dest in self._phyref:
self._phyref[name] = self._phyref[dest]
else:
scan_next[name] = dest
scan = scan_next
attempts += 1
def _ReadPackedRefs(self):
path = os.path.join(self._gitdir, 'packed-refs')
try:
fd = open(path, 'rt')
mtime = os.path.getmtime(path)
except IOError:
return
except OSError:
return
try:
for line in fd:
if line[0] == '#':
continue
if line[0] == '^':
continue
line = line[:-1]
p = line.split(' ')
ref_id = p[0]
name = p[1]
self._phyref[name] = ref_id
finally:
fd.close()
self._mtime['packed-refs'] = mtime
def _ReadLoose(self, prefix):
base = os.path.join(self._gitdir, prefix)
for name in os.listdir(base):
p = os.path.join(base, name)
if os.path.isdir(p):
self._mtime[prefix] = os.path.getmtime(base)
self._ReadLoose(prefix + name + '/')
elif name.endswith('.lock'):
pass
else:
self._ReadLoose1(p, prefix + name)
def _ReadLoose1(self, path, name):
try:
fd = open(path, 'rt')
except IOError:
return
try:
try:
mtime = os.path.getmtime(path)
ref_id = fd.readline()
except (IOError, OSError):
return
finally:
fd.close()
if not ref_id:
return
ref_id = ref_id[:-1]
if ref_id.startswith('ref: '):
self._symref[name] = ref_id[5:]
else:
scan_next[name] = dest
scan = scan_next
attempts += 1
def _ReadPackedRefs(self):
path = os.path.join(self._gitdir, 'packed-refs')
try:
fd = open(path, 'rt')
mtime = os.path.getmtime(path)
except IOError:
return
except OSError:
return
try:
for line in fd:
if line[0] == '#':
continue
if line[0] == '^':
continue
line = line[:-1]
p = line.split(' ')
ref_id = p[0]
name = p[1]
self._phyref[name] = ref_id
finally:
fd.close()
self._mtime['packed-refs'] = mtime
def _ReadLoose(self, prefix):
base = os.path.join(self._gitdir, prefix)
for name in os.listdir(base):
p = os.path.join(base, name)
if os.path.isdir(p):
self._mtime[prefix] = os.path.getmtime(base)
self._ReadLoose(prefix + name + '/')
elif name.endswith('.lock'):
pass
else:
self._ReadLoose1(p, prefix + name)
def _ReadLoose1(self, path, name):
try:
fd = open(path, 'rt')
except IOError:
return
try:
try:
mtime = os.path.getmtime(path)
ref_id = fd.readline()
except (IOError, OSError):
return
finally:
fd.close()
if not ref_id:
return
ref_id = ref_id[:-1]
if ref_id.startswith('ref: '):
self._symref[name] = ref_id[5:]
else:
self._phyref[name] = ref_id
self._mtime[name] = mtime
self._phyref[name] = ref_id
self._mtime[name] = mtime
This diff is collapsed.
This diff is collapsed.
......@@ -20,66 +20,69 @@ import sys
active = False
def RunPager(globalConfig):
global active
if not os.isatty(0) or not os.isatty(1):
return
pager = _SelectPager(globalConfig)
if pager == '' or pager == 'cat':
return
# This process turns into the pager; a child it forks will
# do the real processing and output back to the pager. This
# is necessary to keep the pager in control of the tty.
#
try:
r, w = os.pipe()
pid = os.fork()
if not pid:
os.dup2(w, 1)
os.dup2(w, 2)
os.close(r)
os.close(w)
active = True
return
os.dup2(r, 0)
os.close(r)
os.close(w)
_BecomePager(pager)
except Exception:
print("fatal: cannot start pager '%s'" % pager, file=sys.stderr)
sys.exit(255)
global active
if not os.isatty(0) or not os.isatty(1):
return
pager = _SelectPager(globalConfig)
if pager == '' or pager == 'cat':
return
# This process turns into the pager; a child it forks will
# do the real processing and output back to the pager. This
# is necessary to keep the pager in control of the tty.
#
try:
r, w = os.pipe()
pid = os.fork()
if not pid:
os.dup2(w, 1)
os.dup2(w, 2)
os.close(r)
os.close(w)
active = True
return
os.dup2(r, 0)
os.close(r)
os.close(w)
_BecomePager(pager)
except Exception:
print("fatal: cannot start pager '%s'" % pager, file=sys.stderr)
sys.exit(255)
def _SelectPager(globalConfig):
try:
return os.environ['GIT_PAGER']
except KeyError:
pass
try:
return os.environ['GIT_PAGER']
except KeyError:
pass
pager = globalConfig.GetString('core.pager')
if pager:
return pager
pager = globalConfig.GetString('core.pager')
if pager:
return pager
try:
return os.environ['PAGER']
except KeyError:
pass
try:
return os.environ['PAGER']
except KeyError:
pass
return 'less'
return 'less'
def _BecomePager(pager):
# Delaying execution of the pager until we have output
# ready works around a long-standing bug in popularly
# available versions of 'less', a better 'more'.
#
_a, _b, _c = select.select([0], [], [0])
os.environ['LESS'] = 'FRSX'
try:
os.execvp(pager, [pager])
except OSError:
os.execv('/bin/sh', ['sh', '-c', pager])
# Delaying execution of the pager until we have output
# ready works around a long-standing bug in popularly
# available versions of 'less', a better 'more'.
#
_a, _b, _c = select.select([0], [], [0])
os.environ['LESS'] = 'FRSX'
try:
os.execvp(pager, [pager])
except OSError:
os.execv('/bin/sh', ['sh', '-c', pager])
......@@ -14,58 +14,65 @@ from repo_trace import REPO_TRACE, IsTrace, Trace
SUBPROCESSES = []
def terminateHandle(signal, frame):
for cmd in SUBPROCESSES:
if cmd:
cmd.terminate()
sys.exit(0)
for cmd in SUBPROCESSES:
if cmd:
cmd.terminate()
sys.exit(0)
def stream2str(stream):
return str(stream, encoding='UTF-8')
return str(stream, encoding='UTF-8')
def isUnix():
if platform.system() == "Windows":
return False
else:
return True
if platform.system() == "Windows":
return False
else:
return True
def isPosix():
return platform.system() != "Windows"
return platform.system() != "Windows"
def toUnixPath(path):
return path.replace('\\', '/')
return path.replace('\\', '/')
def toWindowsPath(path):
return path.replace('/', '\\')
return path.replace('/', '\\')
def os_link(src, dst):
if isUnix():
# requires src in relation to dst
src = os.path.relpath(src, os.path.dirname(dst))
os.symlink(src, dst)
else:
isDir = True if os.path.isdir(src) else False
src = os.path.relpath(src, os.path.dirname(dst))
src = toWindowsPath(src)
dst = toWindowsPath(dst)
# ln in MinGW does not create hard links? - it copies
# call windows cmd tool 'mklink' from git bash (mingw)
if isDir:
cmd = 'cmd /c mklink /D "%s" "%s"' % (dst, src)
if IsTrace():
Trace(cmd)
subprocess.Popen(cmd, stdout=subprocess.PIPE).wait()
if isUnix():
# requires src in relation to dst
src = os.path.relpath(src, os.path.dirname(dst))
os.symlink(src, dst)
else:
cmd = 'cmd /c mklink "%s" "%s"' % (dst, src)
if IsTrace():
Trace(cmd)
subprocess.Popen(cmd, stdout=subprocess.PIPE).wait()
isDir = True if os.path.isdir(src) else False
src = os.path.relpath(src, os.path.dirname(dst))
src = toWindowsPath(src)
dst = toWindowsPath(dst)
# ln in MinGW does not create hard links? - it copies
# call windows cmd tool 'mklink' from git bash (mingw)
if isDir:
cmd = 'cmd /c mklink /D "%s" "%s"' % (dst, src)
if IsTrace():
Trace(cmd)
subprocess.Popen(cmd, stdout=subprocess.PIPE).wait()
else:
cmd = 'cmd /c mklink "%s" "%s"' % (dst, src)
if IsTrace():
Trace(cmd)
subprocess.Popen(cmd, stdout=subprocess.PIPE).wait()
def removeReadOnlyFilesHandler(fn, path, excinfo):
removeReadOnlyFiles(fn, path)
def removeReadOnlyFiles(fn, path):
if not os.access(path, os.W_OK):
os.chmod(path, stat.S_IWUSR)
......
......@@ -20,59 +20,60 @@ from repo_trace import IsTrace
_NOT_TTY = not os.isatty(2)
class Progress(object):
def __init__(self, title, total=0, units=''):
self._title = title
self._total = total
self._done = 0
self._lastp = -1
self._start = time()
self._show = False
self._units = units
def __init__(self, title, total=0, units=''):
self._title = title
self._total = total
self._done = 0
self._lastp = -1
self._start = time()
self._show = False
self._units = units
def update(self, inc=1):
self._done += inc
def update(self, inc=1):
self._done += inc
if _NOT_TTY or IsTrace():
return
if _NOT_TTY or IsTrace():
return
if not self._show:
if 0.5 <= time() - self._start:
self._show = True
else:
return
if not self._show:
if 0.5 <= time() - self._start:
self._show = True
else:
return
if self._total <= 0:
sys.stderr.write('\r%s: %d, ' % (
self._title,
self._done))
sys.stderr.flush()
else:
p = (100 * self._done) / self._total
if self._total <= 0:
sys.stderr.write('\r%s: %d, ' % (
self._title,
self._done))
sys.stderr.flush()
else:
p = (100 * self._done) / self._total
if self._lastp != p:
self._lastp = p
sys.stderr.write('\r%s: %3d%% (%d%s/%d%s) ' % (
self._title,
p,
self._done, self._units,
self._total, self._units))
sys.stderr.flush()
if self._lastp != p:
self._lastp = p
sys.stderr.write('\r%s: %3d%% (%d%s/%d%s) ' % (
self._title,
p,
self._done, self._units,
self._total, self._units))
sys.stderr.flush()
def end(self):
if _NOT_TTY or IsTrace() or not self._show:
return
def end(self):
if _NOT_TTY or IsTrace() or not self._show:
return
if self._total <= 0:
sys.stderr.write('\r%s: %d, done. \n' % (
self._title,
self._done))
sys.stderr.flush()
else:
p = (100 * self._done) / self._total
sys.stderr.write('\r%s: %3d%% (%d%s/%d%s), done. \n' % (
self._title,
p,
self._done, self._units,
self._total, self._units))
sys.stderr.flush()
if self._total <= 0:
sys.stderr.write('\r%s: %d, done. \n' % (
self._title,
self._done))
sys.stderr.flush()
else:
p = (100 * self._done) / self._total
sys.stderr.write('\r%s: %3d%% (%d%s/%d%s), done. \n' % (
self._title,
p,
self._done, self._units,
self._total, self._units))
sys.stderr.flush()
This diff is collapsed.
This diff is collapsed.
......@@ -16,20 +16,24 @@
import sys
import os
REPO_TRACE = 'REPO_TRACE'
try:
_TRACE = os.environ[REPO_TRACE] == '1'
_TRACE = os.environ[REPO_TRACE] == '1'
except KeyError:
_TRACE = False
_TRACE = False
def IsTrace():
return _TRACE
return _TRACE
def SetTrace():
global _TRACE
_TRACE = True
global _TRACE
_TRACE = True
def Trace(fmt, *args):
if IsTrace():
print(fmt % args, file=sys.stderr)
if IsTrace():
print(fmt % args, file=sys.stderr)
......@@ -19,31 +19,31 @@ all_commands = {}
my_dir = os.path.dirname(__file__)
for py in os.listdir(my_dir):
if py == '__init__.py':
continue
if py.endswith('.py'):
name = py[:-3]
clsn = name.capitalize()
while clsn.find('_') > 0:
h = clsn.index('_')
clsn = clsn[0:h] + clsn[h + 1:].capitalize()
mod = __import__(__name__,
globals(),
locals(),
['%s' % name])
mod = getattr(mod, name)
try:
cmd = getattr(mod, clsn)()
except AttributeError:
raise SyntaxError('%s/%s does not define class %s' % (
__name__, py, clsn))
name = name.replace('_', '-')
cmd.NAME = name
all_commands[name] = cmd
if py == '__init__.py':
continue
if py.endswith('.py'):
name = py[:-3]
clsn = name.capitalize()
while clsn.find('_') > 0:
h = clsn.index('_')
clsn = clsn[0:h] + clsn[h + 1:].capitalize()
mod = __import__(__name__,
globals(),
locals(),
['%s' % name])
mod = getattr(mod, name)
try:
cmd = getattr(mod, clsn)()
except AttributeError:
raise SyntaxError('%s/%s does not define class %s' % (
__name__, py, clsn))
name = name.replace('_', '-')
cmd.NAME = name
all_commands[name] = cmd
if 'help' in all_commands:
all_commands['help'].commands = all_commands
all_commands['help'].commands = all_commands
......@@ -19,10 +19,11 @@ from command import Command
from git_command import git
from progress import Progress
class Abandon(Command):
common = True
helpSummary = "Permanently abandon a development branch"
helpUsage = """
common = True
helpSummary = "Permanently abandon a development branch"
helpUsage = """
%prog <branchname> [<project>...]
This subcommand permanently abandons a development branch by
......@@ -31,41 +32,41 @@ deleting it (and all its history) from your local repository.
It is equivalent to "git branch -D <branchname>".
"""
def Execute(self, opt, args):
if not args:
self.Usage()
def Execute(self, opt, args):
if not args:
self.Usage()
nb = args[0]
if not git.check_ref_format('heads/%s' % nb):
print("error: '%s' is not a valid name" % nb, file=sys.stderr)
sys.exit(1)
nb = args[0]
if not git.check_ref_format('heads/%s' % nb):
print("error: '%s' is not a valid name" % nb, file=sys.stderr)
sys.exit(1)
nb = args[0]
err = []
success = []
all_projects = self.GetProjects(args[1:])
nb = args[0]
err = []
success = []
all_projects = self.GetProjects(args[1:])
pm = Progress('Abandon %s' % nb, len(all_projects))
for project in all_projects:
pm.update()
pm = Progress('Abandon %s' % nb, len(all_projects))
for project in all_projects:
pm.update()
status = project.AbandonBranch(nb)
if status is not None:
if status:
success.append(project)
else:
err.append(project)
pm.end()
status = project.AbandonBranch(nb)
if status is not None:
if status:
success.append(project)
else:
err.append(project)
pm.end()
if err:
for p in err:
print("error: %s/: cannot abandon %s" % (p.relpath, nb),
file=sys.stderr)
sys.exit(1)
elif not success:
print('error: no project has branch %s' % nb, file=sys.stderr)
sys.exit(1)
else:
print('Abandoned in %d project(s):\n %s'
% (len(success), '\n '.join(p.relpath for p in success)),
file=sys.stderr)
if err:
for p in err:
print("error: %s/: cannot abandon %s" % (p.relpath, nb),
file=sys.stderr)
sys.exit(1)
elif not success:
print('error: no project has branch %s' % nb, file=sys.stderr)
sys.exit(1)
else:
print('Abandoned in %d project(s):\n %s'
% (len(success), '\n '.join(p.relpath for p in success)),
file=sys.stderr)
......@@ -18,47 +18,49 @@ import sys
from color import Coloring
from command import Command
class BranchColoring(Coloring):
def __init__(self, config):
Coloring.__init__(self, config, 'branch')
self.current = self.printer('current', fg='green')
self.local = self.printer('local')
self.notinproject = self.printer('notinproject', fg='red')
def __init__(self, config):
Coloring.__init__(self, config, 'branch')
self.current = self.printer('current', fg='green')
self.local = self.printer('local')
self.notinproject = self.printer('notinproject', fg='red')
class BranchInfo(object):
def __init__(self, name):
self.name = name
self.current = 0
self.published = 0
self.published_equal = 0
self.projects = []
def add(self, b):
if b.current:
self.current += 1
if b.published:
self.published += 1
if b.revision == b.published:
self.published_equal += 1
self.projects.append(b)
@property
def IsCurrent(self):
return self.current > 0
@property
def IsPublished(self):
return self.published > 0
@property
def IsPublishedEqual(self):
return self.published_equal == len(self.projects)
def __init__(self, name):
self.name = name
self.current = 0
self.published = 0
self.published_equal = 0
self.projects = []
def add(self, b):
if b.current:
self.current += 1
if b.published:
self.published += 1
if b.revision == b.published:
self.published_equal += 1
self.projects.append(b)
@property
def IsCurrent(self):
return self.current > 0
@property
def IsPublished(self):
return self.published > 0
@property
def IsPublishedEqual(self):
return self.published_equal == len(self.projects)
class Branches(Command):
common = True
helpSummary = "View current topic branches"
helpUsage = """
common = True
helpSummary = "View current topic branches"
helpUsage = """
%prog [<project>...]
Summarizes the currently available topic branches.
......@@ -91,77 +93,77 @@ is shown, then the branch appears in all projects.
"""
def Execute(self, opt, args):
projects = self.GetProjects(args)
out = BranchColoring(self.manifest.manifestProject.config)
all_branches = {}
project_cnt = len(projects)
for project in projects:
for name, b in list(project.GetBranches().items()):
b.project = project
if name not in all_branches:
all_branches[name] = BranchInfo(name)
all_branches[name].add(b)
names = list(all_branches.keys())
names.sort()
if not names:
print(' (no branches)', file=sys.stderr)
return
width = 25
for name in names:
if width < len(name):
width = len(name)
for name in names:
i = all_branches[name]
in_cnt = len(i.projects)
if i.IsCurrent:
current = '*'
hdr = out.current
else:
current = ' '
hdr = out.local
if i.IsPublishedEqual:
published = 'P'
elif i.IsPublished:
published = 'p'
else:
published = ' '
hdr('%c%c %-*s' % (current, published, width, name))
out.write(' |')
if in_cnt < project_cnt:
fmt = out.write
paths = []
if in_cnt < project_cnt - in_cnt:
in_type = 'in'
for b in i.projects:
paths.append(b.project.relpath)
else:
fmt = out.notinproject
in_type = 'not in'
have = set()
for b in i.projects:
have.add(b.project)
for p in projects:
if not p in have:
paths.append(p.relpath)
s = ' %s %s' % (in_type, ', '.join(paths))
if width + 7 + len(s) < 80:
fmt(s)
else:
fmt(' %s:' % in_type)
for p in paths:
def Execute(self, opt, args):
projects = self.GetProjects(args)
out = BranchColoring(self.manifest.manifestProject.config)
all_branches = {}
project_cnt = len(projects)
for project in projects:
for name, b in list(project.GetBranches().items()):
b.project = project
if name not in all_branches:
all_branches[name] = BranchInfo(name)
all_branches[name].add(b)
names = list(all_branches.keys())
names.sort()
if not names:
print(' (no branches)', file=sys.stderr)
return
width = 25
for name in names:
if width < len(name):
width = len(name)
for name in names:
i = all_branches[name]
in_cnt = len(i.projects)
if i.IsCurrent:
current = '*'
hdr = out.current
else:
current = ' '
hdr = out.local
if i.IsPublishedEqual:
published = 'P'
elif i.IsPublished:
published = 'p'
else:
published = ' '
hdr('%c%c %-*s' % (current, published, width, name))
out.write(' |')
if in_cnt < project_cnt:
fmt = out.write
paths = []
if in_cnt < project_cnt - in_cnt:
in_type = 'in'
for b in i.projects:
paths.append(b.project.relpath)
else:
fmt = out.notinproject
in_type = 'not in'
have = set()
for b in i.projects:
have.add(b.project)
for p in projects:
if not p in have:
paths.append(p.relpath)
s = ' %s %s' % (in_type, ', '.join(paths))
if width + 7 + len(s) < 80:
fmt(s)
else:
fmt(' %s:' % in_type)
for p in paths:
out.nl()
fmt(width * ' ' + ' %s' % p)
else:
out.write(' in all projects')
out.nl()
fmt(width*' ' + ' %s' % p)
else:
out.write(' in all projects')
out.nl()
......@@ -18,13 +18,14 @@ import sys
from command import Command
from progress import Progress
class Checkout(Command):
common = True
helpSummary = "Checkout a branch for development"
helpUsage = """
common = True
helpSummary = "Checkout a branch for development"
helpUsage = """
%prog <branchname> [<project>...]
"""
helpDescription = """
helpDescription = """
The '%prog' command checks out an existing branch that was previously
created by 'repo start'.
......@@ -33,32 +34,32 @@ The command is equivalent to:
repo forall [<project>...] -c git checkout <branchname>
"""
def Execute(self, opt, args):
if not args:
self.Usage()
def Execute(self, opt, args):
if not args:
self.Usage()
nb = args[0]
err = []
success = []
all_projects = self.GetProjects(args[1:])
nb = args[0]
err = []
success = []
all_projects = self.GetProjects(args[1:])
pm = Progress('Checkout %s' % nb, len(all_projects))
for project in all_projects:
pm.update()
pm = Progress('Checkout %s' % nb, len(all_projects))
for project in all_projects:
pm.update()
status = project.CheckoutBranch(nb)
if status is not None:
if status:
success.append(project)
else:
err.append(project)
pm.end()
status = project.CheckoutBranch(nb)
if status is not None:
if status:
success.append(project)
else:
err.append(project)
pm.end()
if err:
for p in err:
print("error: %s/: cannot checkout %s" % (p.relpath, nb),
file=sys.stderr)
sys.exit(1)
elif not success:
print('error: no project has branch %s' % nb, file=sys.stderr)
sys.exit(1)
if err:
for p in err:
print("error: %s/: cannot checkout %s" % (p.relpath, nb),
file=sys.stderr)
sys.exit(1)
elif not success:
print('error: no project has branch %s' % nb, file=sys.stderr)
sys.exit(1)
......@@ -22,94 +22,95 @@ import portable
CHANGE_ID_RE = re.compile(r'^\s*Change-Id: I([0-9a-f]{40})\s*$')
class CherryPick(Command):
common = True
helpSummary = "Cherry-pick a change."
helpUsage = """
common = True
helpSummary = "Cherry-pick a change."
helpUsage = """
%prog <sha1>
"""
helpDescription = """
helpDescription = """
'%prog' cherry-picks a change from one branch to another.
The change id will be updated, and a reference to the old
change id will be added.
"""
def _Options(self, p):
pass
def Execute(self, opt, args):
if len(args) != 1:
self.Usage()
reference = args[0]
p = GitCommand(None,
['rev-parse', '--verify', reference],
capture_stdout = True,
capture_stderr = True)
if p.Wait() != 0:
print(p.stderr, file=sys.stderr)
sys.exit(1)
sha1 = p.stdout.strip()
p = GitCommand(None, ['cat-file', 'commit', sha1], capture_stdout=True)
if p.Wait() != 0:
print("error: Failed to retrieve old commit message", file=sys.stderr)
sys.exit(1)
old_msg = self._StripHeader(portable.stream2str(p.stdout))
p = GitCommand(None,
['cherry-pick', sha1],
capture_stdout = True,
capture_stderr = True)
status = p.Wait()
print(p.stdout, file=sys.stdout)
print(p.stderr, file=sys.stderr)
if status == 0:
# The cherry-pick was applied correctly. We just need to edit the
# commit message.
new_msg = self._Reformat(old_msg, sha1)
p = GitCommand(None, ['commit', '--amend', '-F', '-'],
provide_stdin = True,
capture_stdout = True,
capture_stderr = True)
p.stdin.write(new_msg)
if p.Wait() != 0:
print("error: Failed to update commit message", file=sys.stderr)
sys.exit(1)
else:
print('NOTE: When committing (please see above) and editing the commit'
'message, please remove the old Change-Id-line and add:')
print(self._GetReference(sha1), file=stderr)
print(file=stderr)
def _IsChangeId(self, line):
return CHANGE_ID_RE.match(line)
def _GetReference(self, sha1):
return "(cherry picked from commit %s)" % sha1
def _StripHeader(self, commit_msg):
lines = commit_msg.splitlines()
return "\n".join(lines[lines.index("")+1:])
def _Reformat(self, old_msg, sha1):
new_msg = []
for line in old_msg.splitlines():
if not self._IsChangeId(line):
new_msg.append(line)
# Add a blank line between the message and the change id/reference
try:
if new_msg[-1].strip() != "":
new_msg.append("")
except IndexError:
pass
new_msg.append(self._GetReference(sha1))
return "\n".join(new_msg)
def _Options(self, p):
pass
def Execute(self, opt, args):
if len(args) != 1:
self.Usage()
reference = args[0]
p = GitCommand(None,
['rev-parse', '--verify', reference],
capture_stdout=True,
capture_stderr=True)
if p.Wait() != 0:
print(p.stderr, file=sys.stderr)
sys.exit(1)
sha1 = p.stdout.strip()
p = GitCommand(None, ['cat-file', 'commit', sha1], capture_stdout=True)
if p.Wait() != 0:
print("error: Failed to retrieve old commit message", file=sys.stderr)
sys.exit(1)
old_msg = self._StripHeader(portable.stream2str(p.stdout))
p = GitCommand(None,
['cherry-pick', sha1],
capture_stdout=True,
capture_stderr=True)
status = p.Wait()
print(p.stdout, file=sys.stdout)
print(p.stderr, file=sys.stderr)
if status == 0:
# The cherry-pick was applied correctly. We just need to edit the
# commit message.
new_msg = self._Reformat(old_msg, sha1)
p = GitCommand(None, ['commit', '--amend', '-F', '-'],
provide_stdin=True,
capture_stdout=True,
capture_stderr=True)
p.stdin.write(new_msg)
if p.Wait() != 0:
print("error: Failed to update commit message", file=sys.stderr)
sys.exit(1)
else:
print('NOTE: When committing (please see above) and editing the commit'
'message, please remove the old Change-Id-line and add:')
print(self._GetReference(sha1), file=stderr)
print(file=stderr)
def _IsChangeId(self, line):
return CHANGE_ID_RE.match(line)
def _GetReference(self, sha1):
return "(cherry picked from commit %s)" % sha1
def _StripHeader(self, commit_msg):
lines = commit_msg.splitlines()
return "\n".join(lines[lines.index("") + 1:])
def _Reformat(self, old_msg, sha1):
new_msg = []
for line in old_msg.splitlines():
if not self._IsChangeId(line):
new_msg.append(line)
# Add a blank line between the message and the change id/reference
try:
if new_msg[-1].strip() != "":
new_msg.append("")
except IndexError:
pass
new_msg.append(self._GetReference(sha1))
return "\n".join(new_msg)
......@@ -15,10 +15,11 @@
from command import PagedCommand
class Diff(PagedCommand):
common = True
helpSummary = "Show changes between commit and working tree"
helpUsage = """
common = True
helpSummary = "Show changes between commit and working tree"
helpUsage = """
%prog [<project>...]
The -u option causes '%prog' to generate diff output with file paths
......@@ -26,15 +27,16 @@ relative to the repository root, so the output can be applied
to the Unix 'patch' command.
"""
def _Options(self, p):
def cmd(option, opt_str, value, parser):
setattr(parser.values, option.dest, list(parser.rargs))
while parser.rargs:
del parser.rargs[0]
p.add_option('-u', '--absolute',
dest='absolute', action='store_true',
help='Paths are relative to the repository root')
def _Options(self, p):
def cmd(option, opt_str, value, parser):
setattr(parser.values, option.dest, list(parser.rargs))
while parser.rargs:
del parser.rargs[0]
p.add_option('-u', '--absolute',
dest='absolute', action='store_true',
help='Paths are relative to the repository root')
def Execute(self, opt, args):
for project in self.GetProjects(args):
project.PrintWorkTreeDiff(opt.absolute)
def Execute(self, opt, args):
for project in self.GetProjects(args):
project.PrintWorkTreeDiff(opt.absolute)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -18,62 +18,63 @@ import re
from command import Command, MirrorSafeCommand
class List(Command, MirrorSafeCommand):
common = True
helpSummary = "List projects and their associated directories"
helpUsage = """
common = True
helpSummary = "List projects and their associated directories"
helpUsage = """
%prog [-f] [<project>...]
%prog [-f] -r str1 [str2]..."
"""
helpDescription = """
helpDescription = """
List all projects; pass '.' to list the project for the cwd.
This is similar to running: repo forall -c 'echo "$REPO_PATH : $REPO_PROJECT"'.
"""
def _Options(self, p, show_smart=True):
p.add_option('-r', '--regex',
dest='regex', action='store_true',
help="Filter the project list based on regex or wildcard matching of strings")
p.add_option('-f', '--fullpath',
dest='fullpath', action='store_true',
help="Display the full work tree path instead of the relative path")
def _Options(self, p, show_smart=True):
p.add_option('-r', '--regex',
dest='regex', action='store_true',
help="Filter the project list based on regex or wildcard matching of strings")
p.add_option('-f', '--fullpath',
dest='fullpath', action='store_true',
help="Display the full work tree path instead of the relative path")
def Execute(self, opt, args):
"""List all projects and the associated directories.
def Execute(self, opt, args):
"""List all projects and the associated directories.
This may be possible to do with 'repo forall', but repo newbies have
trouble figuring that out. The idea here is that it should be more
discoverable.
This may be possible to do with 'repo forall', but repo newbies have
trouble figuring that out. The idea here is that it should be more
discoverable.
Args:
opt: The options.
args: Positional args. Can be a list of projects to list, or empty.
"""
if not opt.regex:
projects = self.GetProjects(args)
else:
projects = self.FindProjects(args)
Args:
opt: The options.
args: Positional args. Can be a list of projects to list, or empty.
"""
if not opt.regex:
projects = self.GetProjects(args)
else:
projects = self.FindProjects(args)
def _getpath(x):
if opt.fullpath:
return x.worktree
return x.relpath
def _getpath(x):
if opt.fullpath:
return x.worktree
return x.relpath
lines = []
for project in projects:
lines.append("%s : %s" % (_getpath(project), project.name))
lines = []
for project in projects:
lines.append("%s : %s" % (_getpath(project), project.name))
lines.sort()
print('\n'.join(lines))
lines.sort()
print('\n'.join(lines))
def FindProjects(self, args):
result = []
for project in self.GetProjects(''):
for arg in args:
pattern = re.compile(r'%s' % arg, re.IGNORECASE)
if pattern.search(project.name) or pattern.search(project.relpath):
result.append(project)
break
result.sort(key=lambda project: project.relpath)
return result
def FindProjects(self, args):
result = []
for project in self.GetProjects(''):
for arg in args:
pattern = re.compile(r'%s' % arg, re.IGNORECASE)
if pattern.search(project.name) or pattern.search(project.relpath):
result.append(project)
break
result.sort(key=lambda project: project.relpath)
return result
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment