Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

`tracext.git.git_fs.py`: Untabify and convert to 4-space indentation …

…according to PEP-8
  • Loading branch information...
commit 4be6c4a5ba041dba4cb51e301895adddb511094f 1 parent 1e8a147
@hvr authored
Showing with 460 additions and 459 deletions.
  1. +460 −459 tracext/git/git_fs.py
View
919 tracext/git/git_fs.py
@@ -1,6 +1,6 @@
# -*- coding: iso-8859-1 -*-
#
-# Copyright (C) 2006,2008 Herbert Valerio Riedel <hvr@gnu.org>
+# Copyright (C) 2006-2010 Herbert Valerio Riedel <hvr@gnu.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -17,532 +17,533 @@
from trac.util.datefmt import FixedOffset, to_timestamp, format_datetime
from trac.util.text import to_unicode
from trac.versioncontrol.api import \
- Changeset, Node, Repository, IRepositoryConnector, NoSuchChangeset, NoSuchNode
+ Changeset, Node, Repository, IRepositoryConnector, NoSuchChangeset, NoSuchNode
from trac.wiki import IWikiSyntaxProvider
from trac.versioncontrol.cache import CachedRepository
from trac.versioncontrol.web_ui import IPropertyRenderer
from trac.config import BoolOption, IntOption, PathOption, Option
from trac.web.chrome import Chrome
-# for some reason CachedRepository doesn't pass-through short_rev()s
-class CachedRepository2(CachedRepository):
- def short_rev(self, path):
- return self.repos.short_rev(path)
- def normalize_rev(self, rev):
- if not rev:
- return self.repos.get_youngest_rev()
- normrev=self.repos.git.verifyrev(rev)
- if normrev is None:
- raise NoSuchChangeset(rev)
- return normrev
-
-
from genshi.builder import tag
-from genshi.core import Markup, escape
from datetime import datetime
-import time, sys
+import sys
-if not sys.version_info[:2] >= (2,5):
- raise TracError("python >= 2.5 dependancy not met")
+if not sys.version_info[:2] >= (2, 5):
+ raise TracError("Python >= 2.5 dependancy not met")
import PyGIT
+
+# for some reason CachedRepository doesn't pass-through short_rev()s
+class CachedRepository2(CachedRepository):
+ def short_rev(self, path):
+ return self.repos.short_rev(path)
+ def normalize_rev(self, rev):
+ if not rev:
+ return self.repos.get_youngest_rev()
+ normrev = self.repos.git.verifyrev(rev)
+ if normrev is None:
+ raise NoSuchChangeset(rev)
+ return normrev
+
+
def _last_iterable(iterable):
- "helper for detecting last iteration in for-loop"
- i = iter(iterable)
- v = i.next()
- for nextv in i:
- yield False, v
- v = nextv
- yield True, v
+ "helper for detecting last iteration in for-loop"
+ i = iter(iterable)
+ v = i.next()
+ for nextv in i:
+ yield False, v
+ v = nextv
+ yield True, v
# helper
def _parse_user_time(s):
- """
- parse author/committer attribute lines and return
- (user,timestamp)
- """
+ """
+ parse author/committer attribute lines and return
+ (user,timestamp)
+ """
- user, time, tz_str = s.rsplit(None, 2)
- tz = FixedOffset((int(tz_str)*6)/10, tz_str)
- time = datetime.fromtimestamp(float(time), tz)
- return user, time
+ user, time, tz_str = s.rsplit(None, 2)
+ tz = FixedOffset((int(tz_str)*6)/10, tz_str)
+ time = datetime.fromtimestamp(float(time), tz)
+ return user, time
class GitConnector(Component):
- implements(IRepositoryConnector, IWikiSyntaxProvider, IPropertyRenderer)
+ implements(IRepositoryConnector, IWikiSyntaxProvider, IPropertyRenderer)
+
+ def __init__(self):
+ self._version = None
+
+ try:
+ self._version = PyGIT.Storage.git_version(git_bin=self._git_bin)
+ except PyGIT.GitError, e:
+ self.log.error("GitError: "+e.message)
+
+ if self._version:
+ self.log.info("detected GIT version %s" % self._version['v_str'])
+ self.env.systeminfo.append(('GIT', self._version['v_str']))
+ if not self._version['v_compatible']:
+ self.log.error("GIT version %s installed not compatible (need >= %s)" %
+ (self._version['v_str'], self._version['v_min_str']))
+
+ def _format_sha_link(self, formatter, ns, sha, label, context=None):
+ reponame = ''
+ if context is None:
+ context = formatter.context
+ if formatter is None:
+ formatter = context # hack
+ while context:
+ if context.resource.realm in ('source', 'changeset'):
+ reponame = context.resource.parent.id
+ break
+ context = context.parent
+ repos = self.env.get_repository(reponame)
+ if repos:
+ try:
+ changeset = repos.get_changeset(sha)
+ return tag.a(label, class_="changeset",
+ title=shorten_line(changeset.message),
+ href=formatter.href.changeset(sha, reponame))
+ except Exception, e:
+ errmsg = to_unicode(e)
+ else:
+ errmsg = "Repository '%s' not found" % reponame
+
+ return tag.a(label, class_="missing changeset",
+ #href=formatter.href.changeset(sha, reponame),
+ title=to_unicode(errmsg), rel="nofollow")
+
+ #######################
+ # IPropertyRenderer
+
+ # relied upon by GitChangeset
+
+ def match_property(self, name, mode):
+ if name in ('Parents', 'Children', 'git-committer', 'git-author') \
+ and mode == 'revprop':
+ return 8 # default renderer has priority 1
+ return 0
+
+ def render_property(self, name, mode, context, props):
+ def sha_link(sha):
+ return self._format_sha_link(None, 'sha', sha, sha, context=context)
+
+ if name in ('Parents', 'Children'):
+ revs = props[name]
+
+ return tag([tag(sha_link(rev), ', ') for rev in revs[:-1]],
+ sha_link(revs[-1]))
+
+ if name in ('git-committer', 'git-author'):
+ user_, time_ = props[name]
+ _str = "%s (%s)" % (Chrome(self.env).format_author(context.req, user_),
+ format_datetime(time_, tzinfo=context.req.tz))
+ return unicode(_str)
+
+ raise TracError("internal error")
+
+ #######################
+ # IWikiSyntaxProvider
+
+ def get_wiki_syntax(self):
+ yield (r'(?:\b|!)[0-9a-fA-F]{40,40}\b',
+ lambda fmt, sha, match:
+ self._format_sha_link(fmt, 'changeset', sha, sha))
+
+ def get_link_resolvers(self):
+ yield ('sha', self._format_sha_link)
+
+ #######################
+ # IRepositoryConnector
+
+ _persistent_cache = BoolOption('git', 'persistent_cache', 'false',
+ "enable persistent caching of commit tree")
+
+ _cached_repository = BoolOption('git', 'cached_repository', 'false',
+ "wrap `GitRepository` in `CachedRepository`")
+
+ _shortrev_len = IntOption('git', 'shortrev_len', 7,
+ "length rev sha sums should be tried to be abbreviated to"
+ " (must be >= 4 and <= 40)")
+
+ _trac_user_rlookup = BoolOption('git', 'trac_user_rlookup', 'false',
+ "enable reverse mapping of git email addresses to trac user ids")
+
+ _use_committer_id = BoolOption('git', 'use_committer_id', 'true',
+ "use git-committer id instead of git-author id as changeset owner")
+
+ _use_committer_time = BoolOption('git', 'use_committer_time', 'true',
+ "use git-committer-author timestamp instead of git-author timestamp"
+ " as changeset timestamp")
+
+ _git_bin = PathOption('git', 'git_bin', '/usr/bin/git',
+ "path to git executable (relative to trac project folder!)")
+
+
+ def get_supported_types(self):
+ yield ("git", 8)
+
+ def get_repository(self, type, dir, params):
+ """GitRepository factory method"""
+ assert type == "git"
+
+ if not self._version:
+ raise TracError("GIT backend not available")
+ elif not self._version['v_compatible']:
+ raise TracError("GIT version %s installed not compatible (need >= %s)" %
+ (self._version['v_str'], self._version['v_min_str']))
+
+ if self._trac_user_rlookup:
+ def rlookup_uid(email):
+ """
+ reverse map 'real name <user@domain.tld>' addresses to trac user ids
- def __init__(self):
- self._version = None
+ returns None if lookup failed
+ """
try:
- self._version = PyGIT.Storage.git_version(git_bin=self._git_bin)
- except PyGIT.GitError, e:
- self.log.error("GitError: "+e.message)
-
- if self._version:
- self.log.info("detected GIT version %s" % self._version['v_str'])
- self.env.systeminfo.append(('GIT', self._version['v_str']))
- if not self._version['v_compatible']:
- self.log.error("GIT version %s installed not compatible (need >= %s)" %
- (self._version['v_str'], self._version['v_min_str']))
-
- def _format_sha_link(self, formatter, ns, sha, label, context=None):
- reponame = ''
- if context is None:
- context = formatter.context
- if formatter is None:
- formatter = context # hack
- while context:
- if context.resource.realm in ('source', 'changeset'):
- reponame = context.resource.parent.id
- break
- context = context.parent
- repos = self.env.get_repository(reponame)
- if repos:
- try:
- changeset = repos.get_changeset(sha)
- return tag.a(label, class_="changeset",
- title=shorten_line(changeset.message),
- href=formatter.href.changeset(sha, reponame))
- except Exception, e:
- errmsg = to_unicode(e)
- else:
- errmsg = "Repository '%s' not found" % reponame
-
- return tag.a(label, class_="missing changeset",
- #href=formatter.href.changeset(sha, reponame),
- title=to_unicode(errmsg), rel="nofollow")
-
- #######################
- # IPropertyRenderer
-
- # relied upon by GitChangeset
-
- def match_property(self, name, mode):
- if name in ('Parents','Children','git-committer','git-author') \
- and mode == 'revprop':
- return 8 # default renderer has priority 1
- return 0
-
- def render_property(self, name, mode, context, props):
- def sha_link(sha):
- return self._format_sha_link(None, 'sha', sha, sha, context=context)
-
- if name in ('Parents','Children'):
- revs = props[name]
-
- return tag([tag(sha_link(rev), ', ') for rev in revs[:-1]],
- sha_link(revs[-1]))
-
- if name in ('git-committer', 'git-author'):
- user_, time_ = props[name]
- _str = "%s (%s)" % (Chrome(self.env).format_author(context.req, user_),
- format_datetime(time_, tzinfo=context.req.tz))
- return unicode(_str)
-
- raise TracError("internal error")
-
- #######################
- # IWikiSyntaxProvider
-
- def get_wiki_syntax(self):
- yield (r'(?:\b|!)[0-9a-fA-F]{40,40}\b',
- lambda fmt, sha, match:
- self._format_sha_link(fmt, 'changeset', sha, sha))
-
- def get_link_resolvers(self):
- yield ('sha', self._format_sha_link)
-
- #######################
- # IRepositoryConnector
-
- _persistent_cache = BoolOption('git', 'persistent_cache', 'false',
- "enable persistent caching of commit tree")
-
- _cached_repository = BoolOption('git', 'cached_repository', 'false',
- "wrap `GitRepository` in `CachedRepository`")
-
- _shortrev_len = IntOption('git', 'shortrev_len', 7,
- "length rev sha sums should be tried to be abbreviated to"
- " (must be >= 4 and <= 40)")
-
- _trac_user_rlookup = BoolOption('git', 'trac_user_rlookup', 'false',
- "enable reverse mapping of git email addresses to trac user ids")
-
- _use_committer_id = BoolOption('git', 'use_committer_id', 'true',
- "use git-committer id instead of git-author id as changeset owner")
-
- _use_committer_time = BoolOption('git', 'use_committer_time', 'true',
- "use git-committer-author timestamp instead of git-author timestamp"
- " as changeset timestamp")
-
- _git_bin = PathOption('git', 'git_bin', '/usr/bin/git', "path to git executable (relative to trac project folder!)")
-
-
- def get_supported_types(self):
- yield ("git", 8)
-
- def get_repository(self, type, dir, params):
- """GitRepository factory method"""
- assert type == "git"
-
- if not self._version:
- raise TracError("GIT backend not available")
- elif not self._version['v_compatible']:
- raise TracError("GIT version %s installed not compatible (need >= %s)" %
- (self._version['v_str'], self._version['v_min_str']))
-
- if self._trac_user_rlookup:
- def rlookup_uid(email):
- """
- reverse map 'real name <user@domain.tld>' addresses to trac user ids
-
- returns None if lookup failed
- """
-
- try:
- _, email = email.rsplit('<', 1)
- email, _ = email.split('>', 1)
- email = email.lower()
- except Exception:
- return None
+ _, email = email.rsplit('<', 1)
+ email, _ = email.split('>', 1)
+ email = email.lower()
+ except Exception:
+ return None
+
+ for _uid, _name, _email in self.env.get_known_users():
+ try:
+ if email == _email.lower():
+ return _uid
+ except Exception:
+ continue
+
+ else:
+ def rlookup_uid(_):
+ return None
+
+ repos = GitRepository(dir, params, self.log,
+ persistent_cache=self._persistent_cache,
+ git_bin=self._git_bin,
+ shortrev_len=self._shortrev_len,
+ rlookup_uid=rlookup_uid,
+ use_committer_id=self._use_committer_id,
+ use_committer_time=self._use_committer_time,
+ )
+
+ if self._cached_repository:
+ repos = CachedRepository2(self.env, repos, self.log)
+ self.log.info("enabled CachedRepository for '%s'" % dir)
+ else:
+ self.log.info("disabled CachedRepository for '%s'" % dir)
+
+ return repos
- for _uid, _name, _email in self.env.get_known_users():
- try:
- if email == _email.lower():
- return _uid
- except Exception:
- continue
+class GitRepository(Repository):
+ """
+ Git repository
+ """
+
+ def __init__(self, path, params, log,
+ persistent_cache=False,
+ git_bin='git',
+ shortrev_len=7,
+ rlookup_uid=lambda _: None,
+ use_committer_id=False,
+ use_committer_time=False,
+ ):
+
+ self.logger = log
+ self.gitrepo = path
+ self.params = params
+ self._shortrev_len = max(4, min(shortrev_len, 40))
+ self.rlookup_uid = rlookup_uid
+ self._use_committer_time = use_committer_time
+ self._use_committer_id = use_committer_id
+
+ self.git = PyGIT.StorageFactory(path, log, not persistent_cache, git_bin=git_bin).getInstance()
+
+ Repository.__init__(self, "git:"+path, self.params, log)
+
+ def close(self):
+ self.git = None
+
+ def get_youngest_rev(self):
+ return self.git.youngest_rev()
+
+ def get_oldest_rev(self):
+ return self.git.oldest_rev()
+
+ def normalize_path(self, path):
+ return path and path.strip('/') or '/'
+
+ def normalize_rev(self, rev):
+ if not rev:
+ return self.get_youngest_rev()
+ normrev = self.git.verifyrev(rev)
+ if normrev is None:
+ raise NoSuchChangeset(rev)
+ return normrev
+
+ def short_rev(self, rev):
+ return self.git.shortrev(self.normalize_rev(rev), min_len=self._shortrev_len)
+
+ def get_node(self, path, rev=None):
+ return GitNode(self, path, rev, self.log)
+
+ def get_quickjump_entries(self, rev):
+ for bname, bsha in self.git.get_branches():
+ yield 'branches', bname, '/', bsha
+ for t in self.git.get_tags():
+ yield 'tags', t, '/', t
+
+ def get_changesets(self, start, stop):
+ for rev in self.git.history_timerange(to_timestamp(start), to_timestamp(stop)):
+ yield self.get_changeset(rev)
+
+ def get_changeset(self, rev):
+ """GitChangeset factory method"""
+ return GitChangeset(self, rev)
+
+ def get_changes(self, old_path, old_rev, new_path, new_rev, ignore_ancestry=0):
+ # TODO: handle renames/copies, ignore_ancestry
+ if old_path != new_path:
+ raise TracError("not supported in git_fs")
+
+ for chg in self.git.diff_tree(old_rev, new_rev, self.normalize_path(new_path)):
+ mode1, mode2, obj1, obj2, action, path, path2 = chg
+
+ kind = Node.FILE
+ if mode2.startswith('04') or mode1.startswith('04'):
+ kind = Node.DIRECTORY
- else:
- def rlookup_uid(_):
- return None
+ change = GitChangeset.action_map[action]
- repos = GitRepository(dir, params, self.log,
- persistent_cache=self._persistent_cache,
- git_bin=self._git_bin,
- shortrev_len=self._shortrev_len,
- rlookup_uid=rlookup_uid,
- use_committer_id=self._use_committer_id,
- use_committer_time=self._use_committer_time,
- )
+ old_node = None
+ new_node = None
- if self._cached_repository:
- repos = CachedRepository2(self.env, repos, self.log)
- self.log.info("enabled CachedRepository for '%s'" % dir)
- else:
- self.log.info("disabled CachedRepository for '%s'" % dir)
+ if change != Changeset.ADD:
+ old_node = self.get_node(path, old_rev)
+ if change != Changeset.DELETE:
+ new_node = self.get_node(path, new_rev)
- return repos
+ yield old_node, new_node, kind, change
-class GitRepository(Repository):
- """
- Git repository
- """
-
- def __init__(self, path, params, log,
- persistent_cache=False,
- git_bin='git',
- shortrev_len=7,
- rlookup_uid=lambda _: None,
- use_committer_id=False,
- use_committer_time=False,
- ):
-
- self.logger = log
- self.gitrepo = path
- self.params = params
- self._shortrev_len = max(4, min(shortrev_len, 40))
- self.rlookup_uid = rlookup_uid
- self._use_committer_time = use_committer_time
- self._use_committer_id = use_committer_id
-
- self.git = PyGIT.StorageFactory(path, log, not persistent_cache,
- git_bin=git_bin).getInstance()
- Repository.__init__(self, "git:"+path, self.params, log)
-
- def close(self):
- self.git = None
-
- def clear(self, youngest_rev=None):
- self.youngest = None
- if youngest_rev is not None:
- self.youngest = self.normalize_rev(youngest_rev)
- self.oldest = None
-
- def get_youngest_rev(self):
- return self.git.youngest_rev()
-
- def get_oldest_rev(self):
- return self.git.oldest_rev()
-
- def normalize_path(self, path):
- return path and path.strip('/') or '/'
-
- def normalize_rev(self, rev):
- if not rev:
- return self.get_youngest_rev()
- normrev=self.git.verifyrev(rev)
- if normrev is None:
- raise NoSuchChangeset(rev)
- return normrev
-
- def short_rev(self, rev):
- return self.git.shortrev(self.normalize_rev(rev), min_len=self._shortrev_len)
-
- def get_node(self, path, rev=None):
- return GitNode(self, path, rev, self.log)
-
- def get_quickjump_entries(self, rev):
- for bname,bsha in self.git.get_branches():
- yield 'branches', bname, '/', bsha
- for t in self.git.get_tags():
- yield 'tags', t, '/', t
-
- def get_changesets(self, start, stop):
- for rev in self.git.history_timerange(to_timestamp(start), to_timestamp(stop)):
- yield self.get_changeset(rev)
-
- def get_changeset(self, rev):
- """GitChangeset factory method"""
- return GitChangeset(self, rev)
-
- def get_changes(self, old_path, old_rev, new_path, new_rev, ignore_ancestry=0):
- # TODO: handle renames/copies, ignore_ancestry
- if old_path != new_path:
- raise TracError("not supported in git_fs")
-
- for chg in self.git.diff_tree(old_rev, new_rev, self.normalize_path(new_path)):
- (mode1,mode2,obj1,obj2,action,path,path2) = chg
-
- kind = Node.FILE
- if mode2.startswith('04') or mode1.startswith('04'):
- kind = Node.DIRECTORY
-
- change = GitChangeset.action_map[action]
-
- old_node = None
- new_node = None
-
- if change != Changeset.ADD:
- old_node = self.get_node(path, old_rev)
- if change != Changeset.DELETE:
- new_node = self.get_node(path, new_rev)
-
- yield (old_node, new_node, kind, change)
-
- def next_rev(self, rev, path=''):
- return self.git.hist_next_revision(rev)
-
- def previous_rev(self, rev, path=''):
- return self.git.hist_prev_revision(rev)
-
- def rev_older_than(self, rev1, rev2):
- rc = self.git.rev_is_anchestor_of(rev1, rev2)
- return rc
-
- def clear(self, youngest_rev=None):
- self.sync()
+ def next_rev(self, rev, path=''):
+ return self.git.hist_next_revision(rev)
+
+ def previous_rev(self, rev, path=''):
+ return self.git.hist_prev_revision(rev)
+
+ def rev_older_than(self, rev1, rev2):
+ rc = self.git.rev_is_anchestor_of(rev1, rev2)
+ return rc
- def sync(self, rev_callback=None, clean=None):
- if rev_callback:
- revs = set(self.git.all_revs())
+ # def clear(self, youngest_rev=None):
+ # self.youngest = None
+ # if youngest_rev is not None:
+ # self.youngest = self.normalize_rev(youngest_rev)
+ # self.oldest = None
- if not self.git.sync():
- return None # nothing expected to change
+ def clear(self, youngest_rev=None):
+ self.sync()
- if rev_callback:
- revs = set(self.git.all_revs()) - revs
- for rev in revs:
- rev_callback(rev)
+ def sync(self, rev_callback=None, clean=None):
+ if rev_callback:
+ revs = set(self.git.all_revs())
+
+ if not self.git.sync():
+ return None # nothing expected to change
+
+ if rev_callback:
+ revs = set(self.git.all_revs()) - revs
+ for rev in revs:
+ rev_callback(rev)
class GitNode(Node):
- def __init__(self, repos, path, rev, log, ls_tree_info=None):
- self.log = log
- self.repos = repos
- self.fs_sha = None # points to either tree or blobs
- self.fs_perm = None
- self.fs_size = None
- rev = rev and str(rev) or 'HEAD'
+ def __init__(self, repos, path, rev, log, ls_tree_info=None):
+ self.log = log
+ self.repos = repos
+ self.fs_sha = None # points to either tree or blobs
+ self.fs_perm = None
+ self.fs_size = None
+ rev = rev and str(rev) or 'HEAD'
- kind = Node.DIRECTORY
- p = path.strip('/')
- if p: # ie. not the root-tree
- if not ls_tree_info:
- ls_tree_info = repos.git.ls_tree(rev, p) or None
- if ls_tree_info:
- [ls_tree_info] = ls_tree_info
+ kind = Node.DIRECTORY
+ p = path.strip('/')
+ if p: # ie. not the root-tree
+ if not ls_tree_info:
+ ls_tree_info = repos.git.ls_tree(rev, p) or None
+ if ls_tree_info:
+ [ls_tree_info] = ls_tree_info
- if not ls_tree_info:
- raise NoSuchNode(path, rev)
+ if not ls_tree_info:
+ raise NoSuchNode(path, rev)
- (self.fs_perm, k, self.fs_sha, self.fs_size, fn) = ls_tree_info
+ self.fs_perm, k, self.fs_sha, self.fs_size, _ = ls_tree_info
- # fix-up to the last commit-rev that touched this node
- rev = repos.git.last_change(rev, p)
+ # fix-up to the last commit-rev that touched this node
+ rev = repos.git.last_change(rev, p)
- if k=='tree':
- pass
- elif k=='blob':
- kind = Node.FILE
- else:
- raise TracError("internal error (got unexpected object kind '%s')" % k)
+ if k == 'tree':
+ pass
+ elif k == 'blob':
+ kind = Node.FILE
+ else:
+ raise TracError("internal error (got unexpected object kind '%s')" % k)
- self.created_path = path
- self.created_rev = rev
+ self.created_path = path
+ self.created_rev = rev
- Node.__init__(self, repos, path, rev, kind)
+ Node.__init__(self, repos, path, rev, kind)
- def __git_path(self):
- "return path as expected by PyGIT"
- p = self.path.strip('/')
- if self.isfile:
- assert p
- return p
- if self.isdir:
- return p and (p + '/')
+ def __git_path(self):
+ "return path as expected by PyGIT"
+ p = self.path.strip('/')
+ if self.isfile:
+ assert p
+ return p
+ if self.isdir:
+ return p and (p + '/')
- raise TracError("internal error")
+ raise TracError("internal error")
- def get_content(self):
- if not self.isfile:
- return None
+ def get_content(self):
+ if not self.isfile:
+ return None
- return self.repos.git.get_file(self.fs_sha)
+ return self.repos.git.get_file(self.fs_sha)
- def get_properties(self):
- return self.fs_perm and {'mode': self.fs_perm } or {}
+ def get_properties(self):
+ return self.fs_perm and {'mode': self.fs_perm } or {}
- def get_annotations(self):
- if not self.isfile:
- return
+ def get_annotations(self):
+ if not self.isfile:
+ return
- return [ rev for (rev,lineno) in self.repos.git.blame(self.rev, self.__git_path()) ]
+ return [ rev for rev, lineno in self.repos.git.blame(self.rev, self.__git_path()) ]
- def get_entries(self):
- if not self.isdir:
- return
+ def get_entries(self):
+ if not self.isdir:
+ return
- for ent in self.repos.git.ls_tree(self.rev, self.__git_path()):
- yield GitNode(self.repos, ent[-1], self.rev, self.log, ent)
+ for ent in self.repos.git.ls_tree(self.rev, self.__git_path()):
+ yield GitNode(self.repos, ent[-1], self.rev, self.log, ent)
- def get_content_type(self):
- if self.isdir:
- return None
+ def get_content_type(self):
+ if self.isdir:
+ return None
- return ''
+ return ''
- def get_content_length(self):
- if not self.isfile:
- return None
+ def get_content_length(self):
+ if not self.isfile:
+ return None
- if self.fs_size is None:
- self.fs_size = self.repos.git.get_obj_size(self.fs_sha)
+ if self.fs_size is None:
+ self.fs_size = self.repos.git.get_obj_size(self.fs_sha)
- return self.fs_size
+ return self.fs_size
- def get_history(self, limit=None):
- # TODO: find a way to follow renames/copies
- for is_last,rev in _last_iterable(self.repos.git.history(self.rev, self.__git_path(), limit)):
- yield (self.path, rev, Changeset.EDIT if not is_last else Changeset.ADD)
+ def get_history(self, limit=None):
+ # TODO: find a way to follow renames/copies
+ for is_last, rev in _last_iterable(self.repos.git.history(self.rev, self.__git_path(), limit)):
+ yield (self.path, rev, Changeset.EDIT if not is_last else Changeset.ADD)
- def get_last_modified(self):
- if not self.isfile:
- return None
+ def get_last_modified(self):
+ if not self.isfile:
+ return None
- try:
- msg, props = self.repos.git.read_commit(self.rev)
- user,ts = _parse_user_time(props['committer'][0])
- except:
- self.log.error("internal error (could not get timestamp from commit '%s')" % self.rev)
- return None
+ try:
+ msg, props = self.repos.git.read_commit(self.rev)
+ user, ts = _parse_user_time(props['committer'][0])
+ except:
+ self.log.error("internal error (could not get timestamp from commit '%s')" % self.rev)
+ return None
- return ts
+ return ts
class GitChangeset(Changeset):
- """
- A Git changeset in the Git repository.
-
- Corresponds to a Git commit blob.
- """
-
- action_map = { # see also git-diff-tree(1) --diff-filter
- 'A': Changeset.ADD,
- 'M': Changeset.EDIT, # modified
- 'T': Changeset.EDIT, # file type (mode) change
- 'D': Changeset.DELETE,
- 'R': Changeset.MOVE, # renamed
- 'C': Changeset.COPY
- } # TODO: U, X, B
-
- def __init__(self, repos, sha):
- self.repos = repos
- try:
- msg, props = repos.git.read_commit(sha)
- except PyGIT.GitErrorSha:
- raise NoSuchChangeset(sha)
- self.props = props
-
- assert 'children' not in props
- _children = list(repos.git.children(sha))
- if _children:
- props['children'] = _children
-
- # use 1st author/committer as changeset owner/timestamp
- if repos._use_committer_time:
- _, time_ = _parse_user_time(props['committer'][0])
- else:
- _, time_ = _parse_user_time(props['author'][0])
-
- if repos._use_committer_id:
- user_, _ = _parse_user_time(props['committer'][0])
- else:
- user_, _ = _parse_user_time(props['author'][0])
-
- # try to resolve email address to trac uid
- user_ = repos.rlookup_uid(user_) or user_
-
- Changeset.__init__(self, repos, rev=sha, message=msg, author=user_, date=time_)
-
- def get_properties(self):
- properties = {}
- if 'parent' in self.props:
- properties['Parents'] = self.props['parent']
- if 'children' in self.props:
- properties['Children'] = self.props['children']
- if 'committer' in self.props:
- properties['git-committer'] = \
+ """
+ A Git changeset in the Git repository.
+
+ Corresponds to a Git commit blob.
+ """
+
+ action_map = { # see also git-diff-tree(1) --diff-filter
+ 'A': Changeset.ADD,
+ 'M': Changeset.EDIT, # modified
+ 'T': Changeset.EDIT, # file type (mode) change
+ 'D': Changeset.DELETE,
+ 'R': Changeset.MOVE, # renamed
+ 'C': Changeset.COPY
+ } # TODO: U, X, B
+
+ def __init__(self, repos, sha):
+ self.repos = repos
+ try:
+ msg, props = repos.git.read_commit(sha)
+ except PyGIT.GitErrorSha:
+ raise NoSuchChangeset(sha)
+ self.props = props
+
+ assert 'children' not in props
+ _children = list(repos.git.children(sha))
+ if _children:
+ props['children'] = _children
+
+ # use 1st author/committer as changeset owner/timestamp
+ if repos._use_committer_time:
+ _, time_ = _parse_user_time(props['committer'][0])
+ else:
+ _, time_ = _parse_user_time(props['author'][0])
+
+ if repos._use_committer_id:
+ user_, _ = _parse_user_time(props['committer'][0])
+ else:
+ user_, _ = _parse_user_time(props['author'][0])
+
+ # try to resolve email address to trac uid
+ user_ = repos.rlookup_uid(user_) or user_
+
+ Changeset.__init__(self, repos, rev=sha, message=msg, author=user_, date=time_)
+
+ def get_properties(self):
+ properties = {}
+ if 'parent' in self.props:
+ properties['Parents'] = self.props['parent']
+ if 'children' in self.props:
+ properties['Children'] = self.props['children']
+ if 'committer' in self.props:
+ properties['git-committer'] = \
_parse_user_time(self.props['committer'][0])
- if 'author' in self.props:
- properties['git-author'] = \
+ if 'author' in self.props:
+ properties['git-author'] = \
_parse_user_time(self.props['author'][0])
- return properties
+ return properties
- def get_changes(self):
- paths_seen = set()
- for parent in self.props.get('parent', [None]):
- for mode1,mode2,obj1,obj2,action,path1,path2 in \
- self.repos.git.diff_tree(parent, self.rev, find_renames=True):
- path = path2 or path1
- p_path, p_rev = path1, parent
+ def get_changes(self):
+ paths_seen = set()
+ for parent in self.props.get('parent', [None]):
+ for mode1, mode2, obj1, obj2, action, path1, path2 in \
+ self.repos.git.diff_tree(parent, self.rev, find_renames=True):
+ path = path2 or path1
+ p_path, p_rev = path1, parent
- kind = Node.FILE
- if mode2.startswith('04') or mode1.startswith('04'):
- kind = Node.DIRECTORY
+ kind = Node.FILE
+ if mode2.startswith('04') or mode1.startswith('04'):
+ kind = Node.DIRECTORY
- action = GitChangeset.action_map[action[0]]
+ action = GitChangeset.action_map[action[0]]
- if action == Changeset.ADD:
- p_path = ''
- p_rev = None
+ if action == Changeset.ADD:
+ p_path = ''
+ p_rev = None
- # CachedRepository expects unique (rev, path, change_type) key
- # this is only an issue in case of merges where files required editing
- if path in paths_seen:
- continue
+ # CachedRepository expects unique (rev, path, change_type) key
+ # this is only an issue in case of merges where files required editing
+ if path in paths_seen:
+ continue
- paths_seen.add(path)
+ paths_seen.add(path)
- yield (to_unicode(path), kind, action, to_unicode(p_path), p_rev)
+ yield (to_unicode(path), kind, action, to_unicode(p_path), p_rev)
Please sign in to comment.
Something went wrong with that request. Please try again.