reorganized component and repository code into separate modules
[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 config
7 import git
8 import log
9
10 Error = RuntimeError
11
12 class Repository(object):
13         def __init__(self, name, path, commits, exclude=None):
14                 self.name = name
15                 self.path = path
16                 self.commits = commits
17                 self.exclude = exclude
18                 self.url = None
19                 self.hash = None
20
21         def get_commit(self):
22                 return self.commits.get(config.board) or self.commits.get(None)
23
24         def init(self):
25                 if git.contains_database(self.path):
26                         url = git.getvar(self.path, 'remote.origin.url')
27                         if url:
28                                 self.url = url
29                                 if config.debug:
30                                         print 'Using', self.url
31                                 return
32
33                 for root in config.roots:
34                         for suffix in ('.git', ''):
35                                 url = '%s/%s%s' % (root, self.name, suffix)
36                                 if config.debug:
37                                         print 'Trying', url
38
39                                 if not git.peek_remote(url, quiet=True):
40                                         continue
41
42                                 self.url = url
43                                 if config.debug:
44                                         print 'Found', url
45                                 return
46
47                 raise Error('Failed to locate repository: ' + self.name)
48
49         def exists(self):
50                 return git.contains_database(self.path)
51
52         def clone(self):
53                 print 'Cloning', self.path
54
55                 if os.path.exists(self.path):
56                         self.__clone_in_place()
57                 else:
58                         git.clone(self.path, self.url, checkout=False)
59
60                 if self.exclude:
61                         git.exclude(self.path, self.exclude)
62
63                 git.reset(self.path, self.get_commit(), hard=True)
64
65         def __clone_in_place(self):
66                 tmp = os.path.join(self.path, 'tmp')
67                 git.clone(tmp, self.url, checkout=False)
68
69                 try:
70                         tmpdb = git.database_path(tmp)
71                         db = git.database_path(self.path)
72
73                         if config.debug:
74                                 print 'Moving git database to', self.path
75
76                         os.rename(tmpdb, db)
77                 finally:
78                         os.rmdir(tmp)
79
80         def rebase(self):
81                 print 'Rebasing', self.path
82
83                 git.remote_update(self.path)
84                 git.rebase(self.path)
85
86         def pull(self):
87                 print 'Pulling', self.path
88
89                 git.pull(self.path)
90
91         def other_files(self):
92                 return git.ls_files(self.path, ['-o'])
93
94         def dirty_files(self):
95                 return git.ls_files(self.path, ['-m', '-d'])
96
97         def clean(self):
98                 print 'Cleaning', self.path
99
100                 paths = [os.path.join(self.path,i) for i in self.other_files()]
101                 paths.sort()
102                 paths.reverse()
103
104                 for path in paths:
105                         if git.contains_database(path):
106                                 continue
107
108                         if config.debug:
109                                 print 'Removing', path
110
111                         if os.path.islink(path) or not os.path.isdir(path):
112                                 os.remove(path)
113                         else:
114                                 remove_tree(path)
115
116         def get_hash(self):
117                 if not self.hash:
118                         self.hash = git.rev_parse(self.path, 'HEAD')
119                 return self.hash
120
121         def describe(self):
122                 return git.describe(self.path)
123
124         def archive(self, name, path):
125                 print 'Archiving', self.path
126
127                 git.archive(self.path, path,
128                             prefix=name + os.path.sep,
129                             treeish=self.get_commit())
130
131         def dump_log(self, path):
132                 print 'Generating change log for', self.path
133
134                 fd = os.open(path, os.O_WRONLY | os.O_CREAT, 0644)
135                 try:
136                         git.log(self.path, [self.get_commit()], fd=fd)
137                 finally:
138                         os.close(fd)