예제 #1
0
def system_date(datestring):
    m = re.match(r"^(.+)([+-]\d\d:?\d\d)$", datestring)
    if m:
        # Time zone included; we parse it ourselves, since "date"
        # would convert it to the local time zone.
        (ds, z) = m.groups()
        try:
            t = Run("date", "+%Y-%m-%d-%H-%M-%S", "-d", ds).output_one_line()
        except RunException:
            return None
    else:
        # Time zone not included; we ask "date" to provide it for us.
        try:
            d = Run("date", "+%Y-%m-%d-%H-%M-%S_%z", "-d",
                    datestring).output_one_line()
        except RunException:
            return None
        (t, z) = d.split("_")
    year, month, day, hour, minute, second = [int(x) for x in t.split("-")]
    try:
        return datetime(year,
                        month,
                        day,
                        hour,
                        minute,
                        second,
                        tzinfo=TimeZone(z))
    except ValueError:
        raise DateException(datestring, "date")
예제 #2
0
def __import_mail_path(mail_path, filename, options):
    with open(mail_path, 'rb') as f:
        mail = f.read()

    msg_path = mail_path + '-msg'
    patch_path = mail_path + '-patch'

    mailinfo_lines = Run(
        'git', 'mailinfo', msg_path, patch_path
    ).encoding(None).decoding(None).raw_input(mail).output_lines(b'\n')

    mailinfo = dict(line.split(b': ', 1) for line in mailinfo_lines if line)

    with open(msg_path, 'rb') as f:
        msg_body = f.read()

    msg_bytes = mailinfo[b'Subject'] + b'\n\n' + msg_body

    with open(patch_path, 'rb') as f:
        diff = f.read()

    __create_patch(
        None if options.mbox else filename,
        decode_utf8_with_latin1(msg_bytes),
        mailinfo[b'Author'].decode('utf-8'),
        mailinfo[b'Email'].decode('utf-8'),
        mailinfo[b'Date'].decode('utf-8'),
        diff,
        options,
    )
예제 #3
0
def add_trailer(message, trailer, name, email):
    trailer_line = '%s: %s <%s>' % (trailer, name, email)
    return (
        Run('git', 'interpret-trailers', '--trailer', trailer_line)
        .raw_input(message)
        .raw_output()
    )
예제 #4
0
파일: config.py 프로젝트: hborchardt/stgit
 def remove_section(self, name):
     """Remove a section in the config file. Silently do nothing if
     the section doesn't exist."""
     Run('git', 'config', '--remove-section', name).returns(
         [0, 1, 128]
     ).discard_stderr().discard_output()
     self._cache.clear()
예제 #5
0
def __import_mail_path(mail_path, filename, options):
    with open(mail_path, 'rb') as f:
        mail = f.read()

    msg_path = mail_path + '-msg'
    patch_path = mail_path + '-patch'

    mailinfo_cmd = ['git', 'mailinfo']
    if options.message_id or config.getbool('stgit.import.message-id'):
        mailinfo_cmd.append('--message-id')
    mailinfo_cmd.extend([msg_path, patch_path])

    mailinfo_lines = (Run(*mailinfo_cmd).encoding(None).decoding(
        None).raw_input(mail).output_lines(b'\n'))

    mailinfo = dict(line.split(b': ', 1) for line in mailinfo_lines if line)

    with open(msg_path, 'rb') as f:
        msg_body = f.read()

    msg_bytes = mailinfo[b'Subject'] + b'\n\n' + msg_body

    with open(patch_path, 'rb') as f:
        diff = f.read()

    __create_patch(
        None if options.mbox else filename,
        decode_utf8_with_latin1(msg_bytes),
        None,
        mailinfo[b'Author'].decode('utf-8'),
        mailinfo[b'Email'].decode('utf-8'),
        mailinfo[b'Date'].decode('utf-8'),
        diff,
        options,
    )
예제 #6
0
def func(parser, options, args):
    if options.clear:
        if options.diff or options.number or options.full or options.graphical:
            parser.error('cannot combine --clear with other options')
        elif args:
            parser.error('cannot combine --clear with patch arguments')

    if options.graphical:
        for o in ['diff', 'number', 'full']:
            if getattr(options, o):
                parser.error('cannot combine --graphical and --%s' % o)

    stack = directory.repository.get_stack(options.branch)
    patches = parse_patches(args, list(stack.patchorder.all))
    logref = log.log_ref(stack.name)
    try:
        logcommit = stack.repository.refs.get(logref)
    except KeyError:
        out.info('Log is empty')
        return

    if options.clear:
        log.delete_log(stack.repository, stack.name)
        return

    stacklog = log.get_log_entry(stack.repository, logref, logcommit)
    pathlim = [os.path.join('patches', pn) for pn in patches]

    if options.graphical:
        cmd = ['gitk', stacklog.simplified.sha1, '--'] + pathlim
        # Discard the exit codes generated by SIGINT, SIGKILL, and SIGTERM.
        Run(*cmd).returns([0, -2, -9, -15]).run()
    else:
        show_log(stacklog.simplified, pathlim, options.number, options.full,
                 options.diff)
예제 #7
0
 def _get_git_dir(self):
     try:
         return Run(
             'git', 'rev-parse', '--git-dir'
         ).discard_stderr().output_one_line()
     except RunException:
         return None
예제 #8
0
def func(parser, options, args):
    """Show commit log and diff
    """
    if options.applied:
        patches = crt_series.get_applied()
    elif options.unapplied:
        patches = crt_series.get_unapplied()
    elif len(args) == 0:
        patches = ['HEAD']
    elif '..' in ' '.join(args):
        # patch ranges
        applied = crt_series.get_applied()
        unapplied = crt_series.get_unapplied()
        patches = parse_patches(args, applied + unapplied + \
                                crt_series.get_hidden(), len(applied))
    else:
        # individual patches or commit ids
        patches = args

    if not options.stat:
        options.diff_flags.extend(color_diff_flags())
    commit_ids = [git_id(crt_series, patch) for patch in patches]
    commit_bytes = b'\n'.join(
        (Run('git', 'show', *(options.diff_flags +
                              [commit_id])).decoding(None).raw_output())
        for commit_id in commit_ids)
    if options.stat:
        commit_bytes = git.diffstat(commit_bytes).encode('utf-8')
    if commit_bytes:
        pager(commit_bytes)
예제 #9
0
파일: config.py 프로젝트: hborchardt/stgit
 def rename_section(self, from_name, to_name):
     """Rename a section in the config file. Silently do nothing if
     the section doesn't exist."""
     Run('git', 'config', '--rename-section', from_name, to_name).returns(
         [0, 1, 128]
     ).run()
     self._cache.clear()
예제 #10
0
def git_describe_version():
    path = sys.path[0]
    try:
        v = Run('git', 'describe', '--tags', '--abbrev=4'
                ).cwd(path).output_one_line()
    except RunException as e:
        raise VersionUnavailable(str(e))
    if not re.match(r'^v[0-9]', v):
        raise VersionUnavailable('%s: bad version' % v)
    try:
        dirty = Run('git', 'diff-index', '--name-only', 'HEAD'
                    ).cwd(path).raw_output()
    except RunException as e:
        raise VersionUnavailable(str(e))
    if dirty:
        v += '-dirty'
    return utils.strip_prefix('v', v)
예제 #11
0
    def run(self, args, env={}):
        """Run the given command with an environment given by self.env.

        @type args: list of strings
        @param args: Command and argument vector
        @type env: dict
        @param env: Extra environment"""
        return Run(*args).env(utils.add_dict(self.env, env))
예제 #12
0
def __check_git_version():
    """Check the minimum GIT version
    """
    from stgit.run import Run
    gitver = Run('git', '--version').output_one_line().split()[2]
    if not __check_min_version(version.git_min_ver, gitver):
        print('GIT version %s or newer required. Found %s'
              % (version.git_min_ver, gitver), file=sys.stderr)
        sys.exit(1)
예제 #13
0
def diffstat(diff):
    """Return the diffstat of the supplied diff."""
    return (
        Run('git', 'apply', '--stat', '--summary')
        .encoding(None)
        .raw_input(diff)
        .decoding('utf-8')
        .raw_output()
    )
예제 #14
0
파일: imprt.py 프로젝트: wildmichael/stgit
def __mailsplit(tmpdir, filename, options):
    mailsplit_cmd = ['git', 'mailsplit', '-d4', '-o' + tmpdir]
    if options.mail:
        mailsplit_cmd.append('-b')
    if options.keep_cr:
        mailsplit_cmd.append('--keep-cr')

    if filename:
        mailsplit_cmd.extend(['--', filename])
        r = Run(*mailsplit_cmd)
    else:
        stdin = os.fdopen(sys.__stdin__.fileno(), 'rb')
        r = Run(*mailsplit_cmd).encoding(None).raw_input(stdin.read())

    num_patches = int(r.output_one_line())

    mail_paths = [os.path.join(tmpdir, '%04d' % n) for n in range(1, num_patches + 1)]

    return mail_paths
예제 #15
0
def show_log(stacklog, pathlim, num, full, show_diff):
    cmd = ['git', 'log']
    if num is not None and num > 0:
        cmd.append('-%d' % num)
    if show_diff:
        cmd.append('-p')
    elif not full:
        cmd.append('--pretty=tformat:%h   %aD   %s')
    cmd.extend([stacklog.sha1, '--'])
    cmd.extend(pathlim)
    Run(*cmd).run()
예제 #16
0
파일: config.py 프로젝트: snits/stgit
 def load(self):
     """Load the whole configuration in __cache unless it has been
     done already."""
     if self.__cache is not None:
         return
     self.__cache = self.__defaults
     lines = Run('git', 'config', '--null',
                 '--list').discard_exitcode().output_lines('\0')
     for line in lines:
         key, value = line.split('\n', 1)
         self.__cache.setdefault(key, []).append(value)
예제 #17
0
def git_describe_version():
    root = sys.path[0] if sys.path[0] else None
    try:
        v = (Run('git', 'describe', '--tags',
                 '--abbrev=4').cwd(root).discard_stderr().output_one_line())
    except RunException as e:
        raise VersionUnavailable(str(e))
    m = re.match(r'^v([0-9].*)', v)
    if m:
        v = m.group(1)
    else:
        raise VersionUnavailable('bad version: %s' % v)
    try:
        dirty = (Run('git', 'diff-index', '--name-only',
                     'HEAD').cwd(root).discard_stderr().raw_output())
    except RunException as e:
        raise VersionUnavailable(str(e))
    if dirty:
        v += '-dirty'
    return v
예제 #18
0
 def default_worktree(self):
     """A L{Worktree} object representing the default work tree."""
     if self._default_worktree is None:
         path = environ_get('GIT_WORK_TREE', None)
         if not path:
             o = Run('git', 'rev-parse', '--show-cdup').output_lines()
             o = o or ['.']
             assert len(o) == 1
             path = o[0]
         self._default_worktree = Worktree(path)
     return self._default_worktree
예제 #19
0
 def __topdir_path(self):
     try:
         lines = Run('git', 'rev-parse', '--show-cdup'
                     ).discard_stderr().output_lines()
         if len(lines) == 0:
             return '.'
         elif len(lines) == 1:
             return lines[0]
         else:
             raise RunException('Too much output')
     except RunException:
         raise DirectoryException('No git repository found')
예제 #20
0
def add_trailers(message, trailers, name, email):
    trailer_args = []
    for trailer, user_value in trailers:
        if user_value is None:
            trailer_args.extend(
                ['--trailer',
                 '%s: %s <%s>' % (trailer, name, email)])
        else:
            trailer_args.extend(
                ['--trailer', '%s: %s' % (trailer, user_value)])
    return (Run('git', 'interpret-trailers',
                *trailer_args).raw_input(message).raw_output())
예제 #21
0
 def sections_matching(self, regexp):
     """Takes a regexp with a single group, matches it against all
     config variables, and returns a list whose members are the
     group contents, for all variable names matching the regexp.
     """
     result = []
     for line in Run('git', 'config', '--get-regexp', '"^%s$"' % regexp
                     ).returns([0, 1]).output_lines():
         m = re.match('^%s ' % regexp, line)
         if m:
             result.append(m.group(1))
     return result
예제 #22
0
def read_commit_dag(branch):
    out.start('Reading commit DAG')
    commits = {}
    patches = set()
    for line in Run('git', 'rev-list', '--parents', '--all').output_lines():
        cs = line.split()
        for id in cs:
            if id not in commits:
                commits[id] = Commit(id)
        for id in cs[1:]:
            commits[cs[0]].parents.add(commits[id])
            commits[id].children.add(commits[cs[0]])
    for line in Run('git', 'show-ref').output_lines():
        id, ref = line.split()
        m = re.match(r'^refs/patches/%s/(.+)$' % re.escape(branch), ref)
        if m and not m.group(1).endswith('.log'):
            c = commits[id]
            c.patch = m.group(1)
            patches.add(c)
    out.done()
    return commits, patches
예제 #23
0
def func(parser, options, args):
    """Show commit log and diff"""
    if args and (options.applied or options.unapplied):
        parser.error('patches may not be given with --applied or --unapplied')
    elif options.applied and options.unapplied:
        parser.error('cannot use both --applied and --unapplied')

    repository = directory.repository
    stack = repository.get_stack(options.branch)
    patchorder = stack.patchorder

    if options.applied:
        commits = [stack.patches.get(pn).commit for pn in patchorder.applied]
    elif options.unapplied:
        commits = [stack.patches.get(pn).commit for pn in patchorder.unapplied]
    elif not args:
        commits = [stack.top]
    elif '..' in ' '.join(args):
        # patch ranges
        patch_names = parse_patches(
            args,
            patchorder.all,
            len(patchorder.applied),
        )
        commits = [stack.patches.get(pn).commit for pn in patch_names]
    else:
        commits = []
        for name in args:
            if stack.patches.exists(name):
                commits.append(stack.patches.get(name).commit)
            else:
                try:
                    commits.append(
                        repository.rev_parse(
                            name, object_type='commit', discard_stderr=True
                        )
                    )
                except RepositoryException:
                    raise RepositoryException(
                        '%s: Unknown patch or revision name' % name
                    )

    cmd = ['git', 'show']
    if options.stat:
        cmd.extend(['--stat', '--summary'])
    else:
        cmd.append('--patch')
        cmd.extend(options.diff_flags)
    cmd.extend(color_diff_flags())
    cmd.extend(commit.sha1 for commit in commits)
    pager(Run(*cmd).decoding(None).raw_output())
예제 #24
0
def git_date(datestring=''):
    try:
        ident = (Run('git', 'var', 'GIT_AUTHOR_IDENT').env({
            'GIT_AUTHOR_NAME':
            'XXX',
            'GIT_AUTHOR_EMAIL':
            'XXX',
            'GIT_AUTHOR_DATE':
            datestring,
        }).output_one_line())
    except RunException:
        return None
    _, _, timestamp, offset = ident.split()
    return datetime.fromtimestamp(int(timestamp), TimeZone(offset))
예제 #25
0
 def load(self):
     """Load the configuration in _cache unless it has been done already."""
     if self._cache is not None:
         return
     self._cache = DEFAULTS.copy()
     lines = Run('git', 'config', '--null', '--list'
                 ).discard_exitcode().output_lines('\0')
     for line in lines:
         try:
             key, value = line.split('\n', 1)
         except ValueError:
             key = line
             value = None
         self._cache.setdefault(key, []).append(value)
예제 #26
0
파일: git.py 프로젝트: MaxKellermann/stgit
def pull(repository='origin', refspec=None):
    """Fetches changes from the remote repository, using 'git pull'
    by default.
    """
    # we update the HEAD
    __clear_head_cache()

    args = [repository]
    if refspec:
        args.append(refspec)

    command = (config.get('branch.%s.stgit.pullcmd' % get_head_file())
               or config.get('stgit.pullcmd'))
    Run(*(command.split() + args)).run()
예제 #27
0
파일: basedir.py 프로젝트: snits/stgit
def get():
    """Return the .git directory location
    """
    global __base_dir

    if not __base_dir:
        if 'GIT_DIR' in os.environ:
            __base_dir = os.environ['GIT_DIR']
        else:
            try:
                __base_dir = Run('git', 'rev-parse', '--git-dir').output_one_line()
            except RunException:
                __base_dir = ''

    return __base_dir
예제 #28
0
def get():
    """Return the .git directory location
    """
    global __base_dir

    if not __base_dir:
        __base_dir = environ_get('GIT_DIR')
        if __base_dir is None:
            try:
                __base_dir = Run('git', 'rev-parse',
                                 '--git-dir').output_one_line()
            except RunException:
                __base_dir = ''

    return __base_dir
예제 #29
0
파일: templates.py 프로젝트: zaneb/stgit
def get_template(tfile):
    """Return the string in the template file passed as argument or
    None if the file wasn't found.
    """
    tmpl_dirs = [
        Run('git', 'rev-parse', '--git-dir').output_one_line(),
        os.path.join(os.path.expanduser('~'), '.stgit', 'templates'),
        os.path.join(sys.prefix, 'share', 'stgit', 'templates'),
        os.path.join(os.path.dirname(__file__), 'templates'),
    ]

    for d in tmpl_dirs:
        tmpl_path = os.path.join(d, tfile)
        if os.path.isfile(tmpl_path):
            with io.open(tmpl_path, 'r') as f:
                return f.read()
    else:
        return None
예제 #30
0
파일: git.py 프로젝트: MaxKellermann/stgit
def rebase(tree_id=None):
    """Rebase the current tree to the give tree_id. The tree_id
    argument may be something other than a GIT id if an external
    command is invoked.
    """
    command = (config.get('branch.%s.stgit.rebasecmd' % get_head_file())
               or config.get('stgit.rebasecmd'))
    if tree_id:
        args = [tree_id]
    elif command:
        args = []
    else:
        raise GitException('Default rebasing requires a commit id')
    if command:
        # clear the HEAD cache as the custom rebase command will update it
        __clear_head_cache()
        Run(*(command.split() + args)).run()
    else:
        # default rebasing
        reset(tree_id)