def get_branch(self): headpath = self.repository._repo.refs.refpath('HEAD') try: content = open(headpath).read() match = re.match(r'^ref: refs/heads/(?P<branch>.+)\n$', content) if match: return match.groupdict()['branch'] else: raise RepositoryError("Couldn't compute workdir's branch") except IOError: # Try naive way... raise RepositoryError("Couldn't compute workdir's branch")
def __init__(self, repository, revision): self._stat_modes = {} self.repository = repository try: commit = self.repository._repo.get_object(revision) if isinstance(commit, objects.Tag): revision = commit.object[1] commit = self.repository._repo.get_object(commit.object[1]) except KeyError: raise RepositoryError("Cannot get object with id %s" % revision) self.raw_id = revision self.id = self.raw_id self.short_id = self.raw_id[:12] self._commit = commit self._tree_id = commit.tree self._committer_property = 'committer' self._author_property = 'author' self._date_property = 'commit_time' self._date_tz_property = 'commit_timezone' self.revision = repository.revisions.index(revision) self.message = commit.message.decode("utf-8") self.nodes = {} self._paths = {}
def get_tree_for_dir(tree, dirname): for name, mode, id in tree.iteritems(): if name == dirname: obj = self.repository._repo[id] if isinstance(obj, objects.Tree): return obj else: raise RepositoryError( "Cannot create directory %s " "at tree %s as path is occupied and is not a " "Tree" % (dirname, tree)) return None
def _run_git_command(cls, cmd, **opts): """ Runs given ``cmd`` as git command and returns tuple (stdout, stderr). :param cmd: git command to be executed :param opts: env options to pass into Subprocess command """ if '_bare' in opts: _copts = [] del opts['_bare'] else: _copts = ['-c', 'core.quotepath=false', ] safe_call = False if '_safe' in opts: #no exc on failure del opts['_safe'] safe_call = True _str_cmd = False if isinstance(cmd, str): cmd = [cmd] _str_cmd = True gitenv = os.environ # need to clean fix GIT_DIR ! if 'GIT_DIR' in gitenv: del gitenv['GIT_DIR'] gitenv['GIT_CONFIG_NOGLOBAL'] = '1' _git_path = options.git_path cmd = [_git_path] + _copts + cmd if _str_cmd: cmd = ' '.join(cmd) try: _opts = dict( env=gitenv, shell=False, ) _opts.update(opts) p = subprocessio.SubprocessIOChunker(cmd, **_opts) except (EnvironmentError, OSError) as err: tb_err = ("Couldn't run git command (%s).\n" "Original error was:%s\n" % (cmd, err)) log.error(tb_err) if safe_call: return '', err else: raise RepositoryError(tb_err) return (b''.join(p.output)).decode('utf-8'), (b''.join(p.error)).decode('utf-8')
def _get_repo(self, create, src_url=None, update_after_clone=False, bare=False): if create and os.path.exists(self.path): raise RepositoryError("Location already exist") if src_url and not create: raise RepositoryError("Create should be set to True if src_url is " "given (clone operation creates repository)") try: if create and src_url: GitRepository._check_url(src_url) self.clone(src_url, update_after_clone, bare) return Repo(self.path) elif create: os.mkdir(self.path) if bare: return Repo.init_bare(self.path) else: return Repo.init(self.path) else: return self._repo except (NotGitRepository, OSError) as err: raise RepositoryError(err)
def remove_tag(self, name, user, message=None, date=None): """ Removes tag with the given ``name``. :param name: name of the tag to be removed :param user: full username, i.e.: "Joe Doe <*****@*****.**>" :param message: message of the tag's removal commit :param date: date of tag's removal commit :raises TagDoesNotExistError: if tag with given name does not exists """ if name not in self.tags: raise TagDoesNotExistError("Tag %s does not exist" % name) tagpath = posixpath.join(self._repo.refs.path, 'refs', 'tags', name) try: os.remove(tagpath) self._parsed_refs = self._get_parsed_refs() self.tags = self._get_tags() except OSError as e: raise RepositoryError(e.strerror)
def get_changesets(self, start=None, end=None, start_date=None, end_date=None, branch_name=None, reverse=False): """ Returns iterator of ``GitChangeset`` objects from start to end (both are inclusive), in ascending date order (unless ``reverse`` is set). :param start: changeset ID, as str; first returned changeset :param end: changeset ID, as str; last returned changeset :param start_date: if specified, changesets with commit date less than ``start_date`` would be filtered out from returned set :param end_date: if specified, changesets with commit date greater than ``end_date`` would be filtered out from returned set :param branch_name: if specified, changesets not reachable from given branch would be filtered out from returned set :param reverse: if ``True``, returned generator would be reversed (meaning that returned changesets would have descending date order) :raise BranchDoesNotExistError: If given ``branch_name`` does not exist. :raise ChangesetDoesNotExistError: If changeset for given ``start`` or ``end`` could not be found. """ if branch_name and branch_name not in self.branches: raise BranchDoesNotExistError("Branch '%s' not found" \ % branch_name) # %H at format means (full) commit hash, initial hashes are retrieved # in ascending date order cmd_template = 'log --date-order --reverse --pretty=format:"%H"' cmd_params = {} if start_date: cmd_template += ' --since "$since"' cmd_params['since'] = start_date.strftime('%m/%d/%y %H:%M:%S') if end_date: cmd_template += ' --until "$until"' cmd_params['until'] = end_date.strftime('%m/%d/%y %H:%M:%S') if branch_name: cmd_template += ' $branch_name' cmd_params['branch_name'] = branch_name else: rev_filter = _git_path = options.git_rev_filter.strip() cmd_template += ' %s' % (rev_filter) cmd = Template(cmd_template).safe_substitute(**cmd_params) revs = self.run_git_command(cmd)[0].splitlines() start_pos = 0 end_pos = len(revs) if start: _start = self._get_revision(start) try: start_pos = revs.index(_start) except ValueError: pass if end is not None: _end = self._get_revision(end) try: end_pos = revs.index(_end) except ValueError: pass if None not in [start, end] and start_pos > end_pos: raise RepositoryError('start cannot be after end') if end_pos is not None: end_pos += 1 revs = revs[start_pos:end_pos] if reverse: revs = reversed(revs) for rev in revs: yield self.get_changeset(rev)