Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: server/git.py

Issue 3554003: Merge remote branch 'cros/upstream' into tempbranch3 (Closed) Base URL: http://git.chromium.org/git/autotest.git
Patch Set: Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « server/autotest.py ('k') | server/git_kernel.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #
2 # Copyright 2007 IBM Corp. Released under the GPL v2
3 # Authors: Ryan Harper <ryanh@us.ibm.com>
4 #
5
6 """ 1 """
7 This module defines a class for handling building from git repos 2 This module defines a class for handling building from git repos
3
4 @author: Ryan Harper (ryanh@us.ibm.com)
5 @copyright: IBM 2007
8 """ 6 """
9 7
10 __author__ = """ 8 import os, warnings, logging
11 ryanh@us.ibm.com (Ryan Harper) 9 from autotest_lib.client.common_lib import error, revision_control
12 """ 10 from autotest_lib.client.bin import os_dep
13
14
15 import os
16 from autotest_lib.client.common_lib import error
17 from autotest_lib.server import utils, installable_object 11 from autotest_lib.server import utils, installable_object
18 12
19 13
20 class GitRepo(installable_object.InstallableObject): 14 class InstallableGitRepo(installable_object.InstallableObject):
21 """ 15 """
22 This class represents a git repo. 16 This class helps to pick a git repo and install it in a host.
23
24 It is used to pull down a local copy of a git repo, check if the local
25 repo is up-to-date, if not update. It delegates the install to
26 implementation classes.
27
28 """ 17 """
29 18 def __init__(self, repodir, giturl, weburl=None):
30 def __init__(self, repodir, giturl, weburl): 19 self.repodir = repodir
31 super(installable_object.InstallableObject, self).__init__()
32 if repodir is None:
33 e_msg = 'You must provide a directory to hold the git repository'
34 raise ValueError(e_msg)
35 self.repodir = utils.sh_escape(repodir)
36 if giturl is None:
37 raise ValueError('You must provide a git URL to the repository')
38 self.giturl = giturl 20 self.giturl = giturl
39 if weburl is None:
40 raise ValueError('You must provide a http URL to the repository')
41 self.weburl = weburl 21 self.weburl = weburl
42 22 self.git_repo = revision_control.GitRepo(self.repodir, self.giturl,
43 # path to .git dir 23 self.weburl)
44 self.gitpath = utils.sh_escape(os.path.join(self.repodir,'.git'))
45
46 # base git command , pointing to gitpath git dir
47 self.gitcmdbase = 'git --git-dir=%s' % self.gitpath
48
49 # default to same remote path as local 24 # default to same remote path as local
50 self.__build = os.path.dirname(self.repodir) 25 self._build = os.path.dirname(self.repodir)
51
52
53 def run(self, command, timeout=None, ignore_status=False):
54 return utils.run(r'%s' % (utils.sh_escape(command)),
55 timeout, ignore_status)
56 26
57 27
58 # base install method 28 # base install method
59 def install(self, host, builddir=None): 29 def install(self, host, builddir=None):
30 """
31 Install a git repo in a host. It works by pushing the downloaded source
32 code to the host.
33
34 @param host: Host object.
35 @param builddir: Directory on the host filesystem that will host the
36 source code.
37 """
60 # allow override of target remote dir 38 # allow override of target remote dir
61 if builddir: 39 if builddir:
62 self.__build = builddir 40 self._build = builddir
63 41
64 # push source to host for install 42 # push source to host for install
65 print 'pushing %s to host:%s' %(self.source_material, self.__build) 43 logging.info('Pushing code dir %s to host %s', self.source_material,
66 host.send_file(self.source_material, self.__build) 44 self._build)
45 host.send_file(self.source_material, self._build)
67 46
68 47
69 def gitcmd(self, cmd, ignore_status=False): 48 def gitcmd(self, cmd, ignore_status=False):
70 return self.run('%s %s'%(self.gitcmdbase, cmd), 49 """
71 ignore_status=ignore_status) 50 Wrapper for a git command.
51
52 @param cmd: Git subcommand (ex 'clone').
53 @param ignore_status: Whether we should supress error.CmdError
54 exceptions if the command did return exit code !=0 (True), or
55 not supress them (False).
56 """
57 return self.git_repo.gitcmd(cmd, ignore_status)
72 58
73 59
74 def get(self, **kwargs): 60 def get(self, **kwargs):
75 """ 61 """
76 This method overrides baseclass get so we can do proper git 62 This method overrides baseclass get so we can do proper git
77 clone/pulls, and check for updated versions. The result of 63 clone/pulls, and check for updated versions. The result of
78 this method will leave an up-to-date version of git repo at 64 this method will leave an up-to-date version of git repo at
79 'giturl' in 'repodir' directory to be used by build/install 65 'giturl' in 'repodir' directory to be used by build/install
80 methods. 66 methods.
67
68 @param **kwargs: Dictionary of parameters to the method get.
81 """ 69 """
82
83 if not self.is_repo_initialized():
84 # this is your first time ...
85 print 'cloning repo...'
86 cmd = 'clone %s %s ' %(self.giturl, self.repodir)
87 rv = self.gitcmd(cmd, True)
88 if rv.exit_status != 0:
89 print rv.stderr
90 raise error.CmdError('Failed to clone git url', rv)
91 else:
92 print rv.stdout
93
94 else:
95 # exiting repo, check if we're up-to-date
96 if self.is_out_of_date():
97 print 'updating repo...'
98 rv = self.gitcmd('pull', True)
99 if rv.exit_status != 0:
100 print rv.stderr
101 e_msg = 'Failed to pull git repo data'
102 raise error.CmdError(e_msg, rv)
103 else:
104 print 'repo up-to-date'
105
106
107 # remember where the source is
108 self.source_material = self.repodir 70 self.source_material = self.repodir
71 return self.git_repo.get(**kwargs)
109 72
110 73
111 def get_local_head(self): 74 def get_local_head(self):
112 cmd = 'log --max-count=1' 75 """
113 gitlog = self.gitcmd(cmd).stdout 76 Get the top commit hash of the current local git branch.
114 77
115 # parsing the commit checksum out of git log 's first entry. 78 @return: Top commit hash of local git branch
116 # Output looks like: 79 """
117 # 80 return self.git_repo.get_local_head()
118 # commit 1dccba29b4e5bf99fb98c324f952386dda5b097f
119 # Merge: 031b69b... df6af41...
120 # Author: Avi Kivity <avi@qumranet.com>
121 # Date: Tue Oct 23 10:36:11 2007 +0200
122 #
123 # Merge home:/home/avi/kvm/linux-2.6
124 return str(gitlog.split('\n')[0]).split()[1]
125 81
126 82
127 def get_remote_head(self): 83 def get_remote_head(self):
128 def __needs_refresh(lines): 84 """
129 tag = '<meta http-equiv="refresh" content="0"/>' 85 Get the top commit hash of the current remote git branch.
130 if len(filter(lambda x: x.startswith(tag), lines)) > 0:
131 return True
132 86
133 return False 87 @return: Top commit hash of remote git branch
134 88 """
135 89 return self.git_repo.get_remote_head()
136 # scan git web interface for revision HEAD's commit tag
137 gitwebaction=';a=commit;h=HEAD'
138 url = self.weburl+gitwebaction
139 max_refresh = 4
140 r = 0
141
142 print 'checking %s for changes' %(url)
143 u = utils.urlopen(url)
144 lines = u.read().split('\n')
145
146 while __needs_refresh(lines) and r < max_refresh:
147 print 'refreshing url'
148 r = r+1
149 u = utils.urlopen(url)
150 lines = u.read().split('\n')
151
152 if r >= max_refresh:
153 e_msg = 'Failed to get remote repo status, refreshed %s times' % r
154 raise IndexError(e_msg)
155
156 # looking for a line like:
157 # <tr><td>commit</td><td # class="sha1">aadea67210c8b9e7a57744a1c2845501 d2cdbac7</td></tr>
158 commit_filter = lambda x: x.startswith('<tr><td>commit</td>')
159 commit_line = filter(commit_filter, lines)
160
161 # extract the sha1 sum from the commit line
162 return str(commit_line).split('>')[4].split('<')[0]
163 90
164 91
165 def is_out_of_date(self): 92 def is_out_of_date(self):
166 local_head = self.get_local_head() 93 """
167 remote_head = self.get_remote_head() 94 Return whether this branch is out of date with regards to remote branch.
168 95
169 # local is out-of-date, pull 96 @return: False, if the branch is outdated, True if it is current.
170 if local_head != remote_head: 97 """
171 return True 98 return self.git_repo.is_out_of_date()
172
173 return False
174 99
175 100
176 def is_repo_initialized(self): 101 def is_repo_initialized(self):
177 # if we fail to get a rv of 0 out of the git log command 102 """
178 # then the repo is bogus 103 Return whether the git repo was already initialized (has a top commit).
179 104
180 cmd = 'log --max-count=1' 105 @return: False, if the repo was initialized, True if it was not.
181 rv = self.gitcmd(cmd, True) 106 """
182 if rv.exit_status == 0: 107 return self.git_repo.is_repo_initialized()
183 return True
184 108
185 return False 109
110 def get_revision(self):
111 """
112 Return current HEAD commit id
113 """
114 return self.git_repo.get_revision()
115
116
117 def checkout(self, remote, local=None):
118 """
119 Check out the git commit id, branch, or tag given by remote.
120
121 Optional give the local branch name as local.
122
123 @param remote: Remote commit hash
124 @param local: Local commit hash
125 @note: For git checkout tag git version >= 1.5.0 is required
126 """
127 return self.git_repo.checkout(remote, local)
128
129
130 def get_branch(self, all=False, remote_tracking=False):
131 """
132 Show the branches.
133
134 @param all: List both remote-tracking branches and local branches (True)
135 or only the local ones (False).
136 @param remote_tracking: Lists the remote-tracking branches.
137 """
138 return self.git_repo.get_branch(all, remote_tracking)
OLDNEW
« no previous file with comments | « server/autotest.py ('k') | server/git_kernel.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698