1 import os
2
3 from twisted.internet import defer
4
5 from buildslave.commands.base import SourceBaseCommand
6 from buildslave import runprocess
7 from buildslave.commands import utils
8 from buildslave.commands.base import AbandonChain
9
10
11 -class Git(SourceBaseCommand):
12 """Git specific VC operation. In addition to the arguments
13 handled by SourceBaseCommand, this command reads the following keys:
14
15 ['repourl'] (required): the upstream GIT repository string
16 ['branch'] (optional): which version (i.e. branch or tag) to
17 retrieve. Default: "master".
18 ['submodules'] (optional): whether to initialize and update
19 submodules. Default: False.
20 ['ignore_ignores']: ignore ignores when purging changes.
21 ['reference'] (optional): use this reference repository to fetch objects
22 """
23
24 header = "git operation"
25
27 SourceBaseCommand.setup(self, args)
28 self.repourl = args['repourl']
29 self.branch = args.get('branch')
30 if not self.branch:
31 self.branch = "master"
32 self.sourcedata = "%s %s\n" % (self.repourl, self.branch)
33 self.submodules = args.get('submodules')
34 self.ignore_ignores = args.get('ignore_ignores', True)
35 self.reference = args.get('reference', None)
36
39
44
46 return os.path.isdir(os.path.join(self._fullSrcdir(), ".git"))
47
48 - def _dovccmd(self, command, cb=None, **kwargs):
59
60
61
62
63
64
66 try:
67 olddata = self.readSourcedata()
68 if not olddata.startswith(self.repourl+' '):
69 return False
70 except IOError:
71 return False
72 return True
73
75 command = ['submodule', 'foreach', 'git', 'clean', '-d', '-f']
76 if self.ignore_ignores:
77 command.append('-x')
78 return self._dovccmd(command)
79
81 return self._dovccmd(['submodule', 'update'], self._cleanSubmodules)
82
84 if self.submodules:
85 return self._dovccmd(['submodule', 'init'], self._updateSubmodules)
86 else:
87 return defer.succeed(0)
88
90
91
92 command = ['branch', '-M', self.branch]
93 return self._dovccmd(command, self._initSubmodules)
94
96 if self.revision:
97 head = self.revision
98 else:
99 head = 'FETCH_HEAD'
100
101
102
103 command = ['reset', '--hard', head]
104 return self._dovccmd(command, self._didHeadCheckout)
105
107
108
109 if hasattr(self.command, 'stderr'):
110 if "Couldn't find remote ref" in self.command.stderr:
111 raise AbandonChain(-1)
112
113
114
115
116
118 try:
119
120 diffbranch = self.sourcedata != self.readSourcedata()
121 except IOError:
122 diffbranch = False
123 if diffbranch:
124 command = ['clean', '-f', '-d']
125 if self.ignore_ignores:
126 command.append('-x')
127 return self._dovccmd(command, self._didClean)
128 return self._didClean(None)
129
131
132
133 command = ['fetch', '-t', self.repourl, '+%s' % self.branch]
134
135
136
137
138 if self.args.get('progress'):
139 command.append('--progress')
140 self.sendStatus({"header": "fetching branch %s from %s\n"
141 % (self.branch, self.repourl)})
142 return self._dovccmd(command, self._didFetch, keepStderr=True)
143
145
146 if self.revision:
147
148 d = self._dovccmd(['reset', '--hard', self.revision],
149 self._initSubmodules)
150
151
152 d.addErrback(self._doFetch)
153 return d
154 else:
155
156 return self._doFetch(None)
157
159
160
161 if self.reference:
162 git_alts_path = os.path.join(self._fullSrcdir(), '.git', 'objects', 'info', 'alternates')
163 git_alts_file = open(git_alts_path, 'w')
164 git_alts_file.write(os.path.join(self.reference, 'objects'))
165 git_alts_file.close()
166 return self.doVCUpdate()
167
169 git = self.getCommand("git")
170
171
172
173 if not self.args.get('revision') and self.args.get('shallow'):
174 cmd = [git, 'clone', '--depth', '1']
175
176 if self.reference:
177 cmd.extend(['--reference', self.reference])
178 cmd.extend([self.repourl, self._fullSrcdir()])
179 c = runprocess.RunProcess(self.builder, cmd, self.builder.basedir,
180 sendRC=False, timeout=self.timeout,
181 maxTime=self.maxTime, usePTY=False)
182 self.command = c
183 cmdexec = c.start()
184 cmdexec.addCallback(self._didInit)
185 return cmdexec
186 else:
187 os.makedirs(self._fullSrcdir())
188 return self._dovccmd(['init'], self._didInit)
189
191 command = ['rev-parse', 'HEAD']
192 def _parse(res):
193 hash = self.command.stdout.strip()
194 if len(hash) != 40:
195 return None
196 return hash
197 return self._dovccmd(command, _parse, keepStdout=True)
198