root/0.10/gitplugin/git_fs.py

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

GitPlugin?:

some minor changes to allow for using branch names (and possibly also tag names) instead of revision numbers (e.g. in the View revision entry field);

see #789

git-svn-id: http://trac-hacks.org/svn/gitplugin@1536 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, NoSuchChangeset, NoSuchNode
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                 normrev=self.git.verifyrev(rev)
47                 if normrev is None:
48                         raise NoSuchChangeset(rev)
49                 return normrev
50
51         def short_rev(self, rev):
52                 return self.git.shortrev(self.normalize_rev(rev))
53
54         def get_oldest_rev(self):
55                 return ""
56
57         def get_node(self, path, rev=None):
58                 #print "get_node", path, rev
59                 return GitNode(self.git, path, rev)
60
61         def get_changeset(self, rev):
62                 #print "get_changeset", rev
63                 return GitChangeset(self.git, rev)
64
65         def get_changes(self, old_path, old_rev, new_path, new_rev):
66                 if old_path != new_path:
67                         raise TracError("not supported in git_fs")
68                 #print "get_changes", (old_path, old_rev, new_path, new_rev)
69
70                 for chg in self.git.diff_tree(old_rev, new_rev, self.normalize_path(new_path)):
71                         #print chg
72                         (mode1,mode2,obj1,obj2,action,path) = chg
73                         kind = Node.FILE
74                         if mode2[0] == '1' or mode2[0] == '1':
75                                 kind = Node.DIRECTORY
76                                
77                         if action == 'A':
78                                 change = Changeset.ADD
79                         elif action == 'M':
80                                 change = Changeset.EDIT
81                         elif action == 'D':
82                                 change = Changeset.DELETE
83                         else:
84                                 raise "OhOh"
85
86                         old_node = None
87                         new_node = None
88
89                         if change != Changeset.ADD:
90                                 old_node = self.get_node(path, old_rev)
91                         if change != Changeset.DELETE:
92                                 new_node = self.get_node(path, new_rev)
93
94                         yield (old_node, new_node, kind, change)
95
96         def next_rev(self, rev, path=''):
97                 #print "next_rev"
98                 for c in self.git.children(rev):
99                         return c
100                 return None
101
102         def previous_rev(self, rev):
103                 #print "previous_rev"
104                 for p in self.git.parents(rev):
105                         return p
106                 return None
107
108         def rev_older_than(self, rev1, rev2):
109                 rc = rev1 in self.git.history(rev2, '', 1)
110                 #print "rev_older_than", (rev1, rev2, rc)
111                 return rc
112
113         def sync(self):
114                 #print "GitRepository.sync"
115                 pass
116
117
118 class GitNode(Node):
119         def __init__(self, git, path, rev, tree_ls_info=None):
120                 self.git = git
121                 self.sha = rev
122                 self.perm = None
123                 self.data_len = None
124                
125                 kind = Node.DIRECTORY
126                 p = path.strip('/')
127                 if p != "":
128                         if tree_ls_info:
129                                 (self.perm,k,self.sha,fn)=tree_ls_info
130                         else:
131                                 [(self.perm,k,self.sha,fn)]=git.tree_ls(rev, p)
132                         rev=self.git.last_change(rev, p)
133                         if k=='tree':
134                                 pass
135                         elif k=='blob':
136                                 kind = Node.FILE
137                         else:
138                                 self.log.debug("kind is "+k)
139                        
140                 Node.__init__(self, path, rev, kind)
141
142                 self.created_path = path
143                 self.created_rev = rev
144
145         def get_content(self):
146                 #print "get_content ", self.path, self.sha
147                 if self.isfile:
148                         return self.git.get_file(self.sha)
149                        
150                 return None
151
152         def get_properties(self):
153                 if self.perm:
154                         return {'mode': self.perm }
155                 return {}
156
157         def get_entries(self):
158                 if self.isfile:
159                         return
160                 if not self.isdir:
161                         return
162                
163                 p = self.path.strip('/')
164                 if p != '': p = p + '/'
165                 for e in self.git.tree_ls(self.rev, p):
166                         yield GitNode(self.git, e[3], self.rev, e)
167        
168         def get_content_type(self):
169                 if self.isdir:
170                         return None
171                 return ''
172
173         def get_content_length(self):
174                 if self.isfile:
175                         if not self.data_len:
176                                 self.data_len = self.git.get_obj_size(self.sha)
177                         return self.data_len
178                 return None
179
180         def get_history(self, limit=None):
181                 p = self.path.strip('/')
182                 for rev in self.git.history(self.rev, p):
183                         yield (self.path, rev, Changeset.EDIT)
184
185
186 class GitChangeset(Changeset):
187         def __init__(self, git, sha):
188                 self.git = git
189                 (msg,props) = git.read_commit(sha)
190                 self.props = props
191
192                 committer = props['committer'][0]
193                 (user,time,tz) = committer.rsplit(None, 2)
194                
195                 Changeset.__init__(self, sha, msg, user, float(time))
196
197         def get_properties(self):
198                 for k in self.props:
199                         v = self.props[k]
200                         if k in ['committer', 'author']:
201                                 yield("git-"+k, ", ".join(v), False, 'author')
202                         if k in ['parent']:
203                                 yield("git-"+k, ", ".join(("[%s]" % c) for c in v), True, 'changeset')
204
205         def get_changes(self):
206                 #print "GitChangeset.get_changes"
207                 prev = self.props.has_key('parent') and self.props['parent'][0] or None
208                 for chg in self.git.diff_tree(prev, self.rev):
209                         #print chg
210                         (mode1,mode2,obj1,obj2,action,path) = chg
211                         kind = Node.FILE
212                         if mode1[0:1] == '04' or mode2[0:1] == '04':
213                                 kind = Node.DIRECTORY
214                                
215                         if action == 'A':
216                                 change = Changeset.ADD
217                         elif action == 'M':
218                                 change = Changeset.EDIT
219                         elif action == 'D':
220                                 change = Changeset.DELETE
221                         else:
222                                 raise "OhOh"
223
224                         yield (path, kind, change, path, prev)
Note: See TracBrowser for help on using the browser.