e037d3f5f14a9df22551ee821d1fc1670835ec95
[matrix.git] / matrix / repositories.py
1 # Copyright (C) 2006-2008 Movial Oy
2 # Authors: Timo Savola <tsavola@movial.fi>
3
4 import os
5
6 import git
7 import log
8 from config import config
9
10 Error = RuntimeError
11
12 class Repository(object):
13         def __init__(self, name, path, branch, exclude=None):
14                 self.name = name
15                 self.path = path
16                 self.branch = branch
17                 self.exclude = exclude
18                 self.__url_branch = None
19                 self.__hash = None
20
21         def __str__(self):
22                 return self.path
23
24         def exists(self):
25                 return git.contains_database(self.path)
26
27         def __get_url_branch(self):
28                 if not self.__url_branch:
29                         if self.exists():
30                                 self.__url_branch = self.__old_url_branch()
31
32                         if not self.__url_branch:
33                                 self.__url_branch = self.__new_url_branch()
34
35                         if config.debug:
36                                 url, branch = self.__url_branch
37                                 print 'Using URL:', url
38                                 print 'Using branch:', branch
39
40                 return self.__url_branch
41
42         def __new_url_branch(self):
43                 for root, branch in config.roots:
44                         for suffix in ('.git', ''):
45                                 url = '%s/%s%s' % (root, self.name, suffix)
46
47                                 if config.debug:
48                                         print 'Trying', url
49
50                                 if git.url_exists(url):
51                                         if self.branch:
52                                                 return url, self.branch
53                                         else:
54                                                 return url, branch
55
56                 raise Error('Failed to locate repository under any root: ' + \
57                             '%s.git' % self.name)
58
59         def __old_url_branch(self):
60                 branch, remote = self.__get_branch_remote()
61
62                 url = git.config_get(self.path, 'remote.%s.url' % remote)
63                 if not url:
64                         return None
65
66                 return url, branch
67
68         def __get_branch_remote(self):
69                 branch = git.branch_active(self.path)
70                 if not branch:
71                         return None
72
73                 remote = git.config_get(self.path, 'branch.%s.remote' % branch)
74                 if not remote:
75                         remote = 'origin'
76                         if config.debug:
77                                 print 'Branch "%s" has no configured remote,' \
78                                       ' assuming "%s"' % (branch, remote)
79
80                 return branch, remote
81
82         def clone(self):
83                 print 'Cloning', self
84
85                 url, branch = self.__get_url_branch()
86
87                 if os.path.exists(self.path):
88                         self.__clone_in_place(url)
89                 else:
90                         git.clone(self.path, url, checkout=False)
91
92                 if self.exclude:
93                         git.exclude(self.path, self.exclude)
94
95                 if branch != git.branch_active(self.path):
96                         remote = 'origin/%s' % branch
97                         git.branch_create(self.path, branch, remote)
98
99                 git.checkout(self.path, branch)
100
101         def __clone_in_place(self, url):
102                 tmp = os.path.join(self.path, 'tmp')
103                 git.clone(tmp, url, checkout=False)
104
105                 try:
106                         tmpdb = git.database_path(tmp)
107                         db = git.database_path(self.path)
108
109                         if config.debug:
110                                 print 'Moving git database to', self.path
111
112                         os.rename(tmpdb, db)
113                 finally:
114                         os.rmdir(tmp)
115
116         def rebase(self):
117                 print 'Rebasing', self
118
119                 git.remote_update(self.path)
120                 git.rebase(self.path)
121
122         def pull(self):
123                 print 'Pulling', self
124
125                 git.pull(self.path)
126
127         def other_files(self):
128                 return git.ls_files(self.path, ['-o'], exclude=self.exclude)
129
130         def is_dirty(self):
131                 return git.any_files(self.path, ['-m', '-d'],
132                                      exclude=self.exclude)
133
134         def clean(self):
135                 print 'Cleaning', self
136
137                 paths = [os.path.join(self.path,i) for i in self.other_files()]
138                 paths.sort()
139                 paths.reverse()
140
141                 for path in paths:
142                         if config.debug:
143                                 print 'Removing', path
144
145                         if os.path.islink(path) or not os.path.isdir(path):
146                                 os.remove(path)
147                         else:
148                                 remove_tree(path)
149
150         def get_hash(self):
151                 if not self.__hash:
152                         self.__hash = git.rev_parse(self.path, 'HEAD')
153                 return self.__hash
154
155         def describe(self):
156                 return git.describe(self.path)
157
158         def archive(self, name, path):
159                 print 'Archiving', self
160
161                 url, branch = self.__get_url_branch()
162
163                 git.archive(self.path, path,
164                             prefix=name + os.path.sep,
165                             treeish=branch)
166
167         def dump_log(self, path):
168                 print 'Generating change log for', self
169
170                 url, branch = self.__get_url_branch()
171
172                 fd = os.open(path, os.O_WRONLY | os.O_CREAT, 0644)
173                 try:
174                         git.log(self.path, [branch], fd=fd)
175                 finally:
176                         os.close(fd)
177
178         def changes(self):
179                 print 'Comparing', self
180
181                 branch, remote = self.__get_branch_remote()
182
183                 output = git.changes(self.path, remote)
184                 if output:
185                         print
186                         for line in output:
187                                 print ' ', line
188                         print
189
190                         return True
191                 else:
192                         return False