root/0.10/gitplugin/git_fs.py

Revision f38c44f85f5ed28372a947f9b97b022936faf4a2, 5.4 kB (checked in by hvr <hvr@7322e99d-02ea-0310-aa39-e9a107903beb>, 8 years ago)

GitPlugin?:

performance improvements

addresses #746

git-svn-id: http://trac-hacks.org/svn/gitplugin@1321 7322e99d-02ea-0310-aa39-e9a107903beb

  • Property mode set to 100644
Line 
1 # -*- coding: iso-8859-1 -*-
2 #
3 # Copyright (C) 2006 Herbert Valerio Riedel <hvr@gnu.org>
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14
15 from trac.core import *
16 from trac.util import TracError, shorten_line, escape
17 from trac.versioncontrol import Changeset, Node, Repository, \
18                                 IRepositoryConnector
19
20 import PyGIT
21
22 class GitConnector(Component):
23         implements(IRepositoryConnector)
24
25         def get_supported_types(self):
26                 yield ("git", 8)
27
28         def get_repository(self, type, dir, authname):
29                 return GitRepository(dir, self.log)
30
31 class GitRepository(Repository):
32         def __init__(self, path, log):
33                 self.gitrepo = path
34                 self.git = PyGIT.Storage(path)
35                 Repository.__init__(self, "git:"+path, None, log)
36
37         def get_youngest_rev(self):
38                 return self.git.head()
39
40         def normalize_path(self, path):
41                 return path and path.strip('/') or ''
42
43         def normalize_rev(self, rev):
44                 if rev=='None' or rev == None or rev == '':
45                         return self.get_youngest_rev()
46                 return rev
47
48         def get_oldest_rev(self):
49                 return ""
50
51         def get_node(self, path, rev=None):
52                 #print "get_node", path, rev
53                 return GitNode(self.git, path, rev)
54
55         def get_changeset(self, rev):
56                 #print "get_changeset", rev
57                 return GitChangeset(self.git, rev)
58
59         def get_changes(self, old_path, old_rev, new_path, new_rev):
60                 if old_path != new_path:
61                         raise TracError("not supported in git_fs")
62                 #print "get_changes", (old_path, old_rev, new_path, new_rev)
63
64                 for chg in self.git.diff_tree(old_rev, new_rev, self.normalize_path(new_path)):
65                         #print chg
66                         (mode1,mode2,obj1,obj2,action,path) = chg
67                         kind = Node.FILE
68                         if mode2[0] == '1' or mode2[0] == '1':
69                                 kind = Node.DIRECTORY
70                                
71                         if action == 'A':
72                                 change = Changeset.ADD
73                         elif action == 'M':
74                                 change = Changeset.EDIT
75                         elif action == 'D':
76                                 change = Changeset.DELETE
77                         else:
78                                 raise "OhOh"
79
80                         old_node = None
81                         new_node = None
82
83                         if change != Changeset.ADD:
84                                 old_node = self.get_node(path, old_rev)
85                         if change != Changeset.DELETE:
86                                 new_node = self.get_node(path, new_rev)
87
88                         yield (old_node, new_node, kind, change)
89
90         def next_rev(self, rev, path=''):
91                 #print "next_rev"
92                 for c in self.git.children(rev):
93                         return c
94                 return None
95
96         def previous_rev(self, rev):
97                 #print "previous_rev"
98                 for p in self.git.parents(rev):
99                         return p
100                 return None
101
102         def rev_older_than(self, rev1, rev2):
103                 rc = rev1 in self.git.history(rev2, '', 1)
104                 #print "rev_older_than", (rev1, rev2, rc)
105                 return rc
106
107         def sync(self):
108                 #print "GitRepository.sync"
109                 pass
110
111
112 class GitNode(Node):
113         def __init__(self, git, path, rev, tree_ls_info=None):
114                 self.git = git
115                 self.sha = rev
116                 self.perm = None
117                 self.data_len = None
118                
119                 kind = Node.DIRECTORY
120                 p = path.strip('/')
121                 if p != "":
122                         if tree_ls_info:
123                                 (self.perm,k,self.sha,fn)=tree_ls_info
124                         else:
125                                 [(self.perm,k,self.sha,fn)]=git.tree_ls(rev, p)
126                         rev=self.git.last_change(rev, p)
127                         if k=='tree':
128                                 pass
129                         elif k=='blob':
130                                 kind = Node.FILE
131                         else:
132                                 self.log.debug("kind is "+k)
133                        
134                 Node.__init__(self, path, rev, kind)
135
136                 self.created_path = path
137                 self.created_rev = rev
138
139         def get_content(self):
140                 #print "get_content ", self.path, self.sha
141                 if self.isfile:
142                         return self.git.get_file(self.sha)
143                        
144                 return None
145
146         def get_properties(self):
147                 if self.perm:
148                         return {'mode': self.perm }
149                 return {}
150
151         def get_entries(self):
152                 if self.isfile:
153                         return
154                 if not self.isdir:
155                         return
156                
157                 p = self.path.strip('/')
158                 if p != '': p = p + '/'
159                 for e in self.git.tree_ls(self.rev, p):
160                         yield GitNode(self.git, e[3], self.rev, e)
161        
162         def get_content_type(self):
163                 if self.isdir:
164                         return None
165                 return ''
166
167         def get_content_length(self):
168                 if self.isfile:
169                         if not self.data_len:
170                                 self.data_len = self.git.get_obj_size(self.sha)
171                         return self.data_len
172                 return None
173
174         def get_history(self, limit=None):
175                 p = self.path.strip('/')
176                 for rev in self.git.history(self.rev, p):
177                         yield (self.path, rev, Changeset.EDIT)
178
179
180 class GitChangeset(Changeset):
181         def __init__(self, git, sha):
182                 self.git = git
183                 (msg,props) = git.read_commit(sha)
184                 self.props = props
185
186                 committer = props['committer'][0]
187                 (user,time,tz) = committer.rsplit(None, 2)
188                
189                 Changeset.__init__(self, sha, msg, user, float(time))
190
191         def get_properties(self):
192                 for k in self.props:
193                         v = self.props[k]
194                         if k in ['committer', 'author']:
195                                 yield("git-"+k, ", ".join(v), False, 'author')
196                         if k in ['parent']:
197                                 yield("git-"+k, ", ".join(("[%s]" % c) for c in v), True, 'changeset')
198
199         def get_changes(self):
200                 #print "GitChangeset.get_changes"
201                 prev = self.props.has_key('parent') and self.props['parent'][0] or None
202                 for chg in self.git.diff_tree(prev, self.rev):
203                         #print chg
204                         (mode1,mode2,obj1,obj2,action,path) = chg
205                         kind = Node.FILE
206                         if mode1[0:1] == '04' or mode2[0:1] == '04':
207                                 kind = Node.DIRECTORY
208                                
209                         if action == 'A':
210                                 change = Changeset.ADD
211                         elif action == 'M':
212                                 change = Changeset.EDIT
213                         elif action == 'D':
214                                 change = Changeset.DELETE
215                         else:
216                                 raise "OhOh"
217
218                         yield (path, kind, change, path, prev)
Note: See TracBrowser for help on using the browser.