def git_commit(name, repository, branch_name=None): """Return the a Commit object if 'name' is a patch name or Git commit. The patch names allowed are in the form '<branch>:<patch>' and can be followed by standard symbols used by git rev-parse. If <patch> is '{base}', it represents the bottom of the stack. If <patch> is {public}, it represents the public branch corresponding to the stack as described in the 'publish' command. """ # Try a [branch:]patch name first branch, patch = parse_rev(name) if not branch: branch = branch_name or repository.current_branch_name # The stack base if patch.startswith('{base}'): base_id = repository.get_stack(branch).base.sha1 return repository.rev_parse(base_id + strip_prefix('{base}', patch)) elif patch.startswith('{public}'): public_ref = get_public_ref(branch) return repository.rev_parse(public_ref + strip_prefix('{public}', patch), discard_stderr=True) # Other combination of branch and patch try: return repository.rev_parse('patches/%s/%s' % (branch, patch), discard_stderr=True) except RepositoryException: pass # Try a Git commit try: return repository.rev_parse(name, discard_stderr=True) except RepositoryException: raise CmdException('%s: Unknown patch or revision name' % name)
def get_head_file(): """Return the name of the file pointed to by the HEAD symref. Throw an exception if HEAD is detached.""" try: return strip_prefix( 'refs/heads/', GRun('symbolic-ref', '-q', 'HEAD' ).output_one_line()) except GitRunException: raise DetachedHeadException()
def get_head_file(): """Return the name of the file pointed to by the HEAD symref. Throw an exception if HEAD is detached.""" try: return strip_prefix( 'refs/heads/', GRun('symbolic-ref', '-q', 'HEAD').output_one_line()) except GitRunException: raise DetachedHeadException()
def metavar(self): o = self.get_option() if not o.takes_value(): return None if o.metavar: return o.metavar for flag in self.pargs: if flag.startswith('--'): return utils.strip_prefix('--', flag).upper() raise Exception('Cannot determine metavar')
def git_commit(name, repository, branch_name = None): """Return the a Commit object if 'name' is a patch name or Git commit. The patch names allowed are in the form '<branch>:<patch>' and can be followed by standard symbols used by git rev-parse. If <patch> is '{base}', it represents the bottom of the stack. If <patch> is {public}, it represents the public branch corresponding to the stack as described in the 'publish' command. """ # Try a [branch:]patch name first branch, patch = parse_rev(name) if not branch: branch = branch_name or repository.current_branch_name # The stack base if patch.startswith('{base}'): base_id = repository.get_stack(branch).base.sha1 return repository.rev_parse(base_id + strip_prefix('{base}', patch)) elif patch.startswith('{public}'): public_ref = get_public_ref(branch) return repository.rev_parse(public_ref + strip_prefix('{public}', patch), discard_stderr = True) # Other combination of branch and patch try: return repository.rev_parse('patches/%s/%s' % (branch, patch), discard_stderr = True) except libgit.RepositoryException: pass # Try a Git commit try: return repository.rev_parse(name, discard_stderr = True) except libgit.RepositoryException: raise CmdException('%s: Unknown patch or revision name' % name)
def _parse_metadata(repo, metadata): """Parse a stack log metadata string.""" if not metadata.startswith('Version:'): raise LogParseException('Malformed log metadata') metadata = metadata.splitlines() version_str = utils.strip_prefix('Version:', metadata.pop(0)).strip() try: version = int(version_str) except ValueError: raise LogParseException('Malformed version number: %r' % version_str) if version < 1: raise LogException('Log is version %d, which is too old' % version) if version > 1: raise LogException('Log is version %d, which is too new' % version) parsed = {} key = None for line in metadata: if line.startswith(' '): assert key is not None parsed[key].append(line.strip()) else: key, val = [x.strip() for x in line.split(':', 1)] if val: parsed[key] = val else: parsed[key] = [] prev = parsed['Previous'] if prev == 'None': prev = None else: prev = repo.get_commit(prev) head = repo.get_commit(parsed['Head']) lists = {'Applied': [], 'Unapplied': [], 'Hidden': []} patches = {} for lst in lists: for entry in parsed[lst]: pn, sha1 = [x.strip() for x in entry.split(':')] lists[lst].append(pn) patches[pn] = repo.get_commit(sha1) return ( prev, head, lists['Applied'], lists['Unapplied'], lists['Hidden'], patches, )
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)
def __parse_metadata(repo, metadata): """Parse a stack log metadata string.""" if not metadata.startswith('Version:'): raise LogParseException('Malformed log metadata') metadata = metadata.splitlines() version_str = utils.strip_prefix('Version:', metadata.pop(0)).strip() try: version = int(version_str) except ValueError: raise LogParseException( 'Malformed version number: %r' % version_str) if version < 1: raise LogException('Log is version %d, which is too old' % version) if version > 1: raise LogException('Log is version %d, which is too new' % version) parsed = {} for line in metadata: if line.startswith(' '): parsed[key].append(line.strip()) else: key, val = [x.strip() for x in line.split(':', 1)] if val: parsed[key] = val else: parsed[key] = [] prev = parsed['Previous'] if prev == 'None': prev = None else: prev = repo.get_commit(prev) head = repo.get_commit(parsed['Head']) lists = { 'Applied': [], 'Unapplied': [], 'Hidden': [] } patches = {} for lst in lists.keys(): for entry in parsed[lst]: pn, sha1 = [x.strip() for x in entry.split(':')] lists[lst].append(pn) patches[pn] = repo.get_commit(sha1) return (prev, head, lists['Applied'], lists['Unapplied'], lists['Hidden'], patches)
def append_alias_commands(cmd_list): for (name, command) in config.getstartswith('stgit.alias.'): name = utils.strip_prefix('stgit.alias.', name) cmd_list[name] = (CommandAlias(name, command), 'Alias commands', command)
def current_branch_name(self): """Return the name of the current branch.""" return utils.strip_prefix('refs/heads/', self.head_ref)
def func(parser, options, args): """Publish the stack changes.""" repository = directory.repository stack = repository.get_stack(options.branch) if not args: public_ref = common.get_public_ref(stack.name) elif len(args) == 1: public_ref = args[0] else: parser.error('incorrect number of arguments') if not public_ref.startswith('refs/heads/'): public_ref = 'refs/heads/' + public_ref # just clone the stack if the public ref does not exist if not repository.refs.exists(public_ref): if options.unpublished or options.last: raise common.CmdException('"%s" does not exist' % public_ref) repository.refs.set(public_ref, stack.head, 'publish') out.info('Created "%s"' % public_ref) return public_head = repository.refs.get(public_ref) public_tree = public_head.data.tree # find the last published patch if options.last: last = __get_last(stack, public_tree) if not last: raise common.CmdException( 'Unable to find the last published patch ' '(possibly rebased stack)' ) out.info('%s' % last) return # check for same tree (already up to date) if public_tree.sha1 == stack.head.data.tree.sha1: out.info('"%s" already up to date' % public_ref) return # check for unpublished patches if options.unpublished: published = set(__get_published(stack, public_tree)) for p in stack.patchorder.applied: if p not in published: out.stdout(p) return if options.overwrite: repository.refs.set(public_ref, stack.head, 'publish') out.info('Overwrote "%s"' % public_ref) return # check for rebased stack. In this case we emulate a merge with the stack # base by setting two parents. merge_bases = set(repository.get_merge_bases(public_head, stack.base)) if public_head in merge_bases: # fast-forward the public ref repository.refs.set(public_ref, stack.head, 'publish') out.info('Fast-forwarded "%s"' % public_ref) return if stack.base not in merge_bases: message = 'Merge %s into %s' % ( repository.describe(stack.base).strip(), utils.strip_prefix('refs/heads/', public_ref), ) public_head = __create_commit( repository, stack.head.data.tree, [public_head, stack.base], options, message, ) repository.refs.set(public_ref, public_head, 'publish') out.info('Merged the stack base into "%s"' % public_ref) return # check for new patches from the last publishing. This is done by checking # whether the public tree is the same as the bottom of the checked patch. # If older patches were modified, new patches cannot be detected. The new # patches and their metadata are pushed directly to the published head. for p in stack.patchorder.applied: pc = stack.patches.get(p).commit if public_tree.sha1 == pc.data.parent.data.tree.sha1: if pc.data.is_nochange(): out.info('Ignored new empty patch "%s"' % p) continue cd = pc.data.set_parent(public_head) public_head = repository.commit(cd) public_tree = public_head.data.tree out.info('Published new patch "%s"' % p) # create a new commit (only happens if no new patches are detected) if public_tree.sha1 != stack.head.data.tree.sha1: public_head = __create_commit(repository, stack.head.data.tree, [public_head], options) # update the public head repository.refs.set(public_ref, public_head, 'publish') out.info('Updated "%s"' % public_ref)
def func(parser, options, args): """Publish the stack changes.""" repository = directory.repository stack = repository.get_stack(options.branch) if not args: public_ref = common.get_public_ref(stack.name) elif len(args) == 1: public_ref = args[0] else: parser.error('incorrect number of arguments') if not public_ref.startswith('refs/heads/'): public_ref = 'refs/heads/' + public_ref # just clone the stack if the public ref does not exist if not repository.refs.exists(public_ref): if options.unpublished or options.last: raise common.CmdException('"%s" does not exist' % public_ref) repository.refs.set(public_ref, stack.head, 'publish') out.info('Created "%s"' % public_ref) return public_head = repository.refs.get(public_ref) public_tree = public_head.data.tree # find the last published patch if options.last: last = __get_last(stack, public_tree) if not last: raise common.CmdException('Unable to find the last published patch ' '(possibly rebased stack)') out.info('%s' % last) return # check for same tree (already up to date) if public_tree.sha1 == stack.head.data.tree.sha1: out.info('"%s" already up to date' % public_ref) return # check for unpublished patches if options.unpublished: published = set(__get_published(stack, public_tree)) for p in stack.patchorder.applied: if p not in published: print p return # check for rebased stack. In this case we emulate a merge with the stack # base by setting two parents. merge_bases = set(repository.get_merge_bases(public_head, stack.base)) if public_head in merge_bases: # fast-forward the public ref repository.refs.set(public_ref, stack.head, 'publish') out.info('Fast-forwarded "%s"' % public_ref) return if not stack.base in merge_bases: message = 'Merge %s into %s' % (repository.describe(stack.base).strip(), utils.strip_prefix('refs/heads/', public_ref)) public_head = __create_commit(repository, stack.head.data.tree, [public_head, stack.base], options, message) repository.refs.set(public_ref, public_head, 'publish') out.info('Merged the stack base into "%s"' % public_ref) return # check for new patches from the last publishing. This is done by checking # whether the public tree is the same as the bottom of the checked patch. # If older patches were modified, new patches cannot be detected. The new # patches and their metadata are pushed directly to the published head. for p in stack.patchorder.applied: pc = stack.patches.get(p).commit if public_tree.sha1 == pc.data.parent.data.tree.sha1: if pc.data.is_nochange(): out.info('Ignored new empty patch "%s"' % p) continue cd = pc.data.set_parent(public_head) public_head = repository.commit(cd) public_tree = public_head.data.tree out.info('Published new patch "%s"' % p) # create a new commit (only happens if no new patches are detected) if public_tree.sha1 != stack.head.data.tree.sha1: public_head = __create_commit(repository, stack.head.data.tree, [public_head], options) # update the public head repository.refs.set(public_ref, public_head, 'publish') out.info('Updated "%s"' % public_ref)
path = sys.path[0] try: v = run.Run('git', 'describe', '--tags', '--abbrev=4' ).cwd(path).output_one_line() except run.RunException, e: raise VersionUnavailable(str(e)) if not re.match(r'^v[0-9]', v): raise VersionUnavailable('%s: bad version' % v) try: dirty = run.Run('git', 'diff-index', '--name-only', 'HEAD' ).cwd(path).raw_output() except run.RunException, e: raise VersionUnavailable(str(e)) if dirty: v += '-dirty' return utils.strip_prefix('v', v) def builtin_version(): try: import builtin_version as bv except ImportError: raise VersionUnavailable() else: return bv.version def _builtin_version_file(ext = 'py'): return os.path.join(sys.path[0], 'stgit', 'builtin_version.%s' % ext) def write_builtin_version(): try: v = git_describe_version()