summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrevor Gamblin <tgamblin@baylibre.com>2024-05-03 09:10:30 -0400
committerRichard Purdie <richard.purdie@linuxfoundation.org>2024-05-13 16:28:35 +0100
commit9132e3904a8f26d49c4c425a0b7d25b71e586890 (patch)
tree8aef932caf8cb1f10ffbca9118b7ea720329ef11
parente73ea1a868331bc60de1717282f1c7a4139eeb30 (diff)
downloadpoky-9132e3904a8f26d49c4c425a0b7d25b71e586890.tar.gz
patchtest: repo: refactor to use GitPython
The repo module currently uses a custom _exec() function in order to run various git commands as part of the patchtest setup/test process. These can more efficiently be done with the GitPython module, so use that instead and reduce the amount of custom code to be maintained for patchtest in the process. Some specifics replaced using GitPython: - get branch list - use repo.active_branch to determine current branch - use execute() for checkout, merge check, abort, rev-parse, reset The _exec() function is removed entirely with this change. (From OE-Core rev: 8ab3a0d7cb68746d7b7e1c7ff8bdf9a84a4d075d) Signed-off-by: Trevor Gamblin <tgamblin@baylibre.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/lib/patchtest/repo.py88
1 files changed, 17 insertions, 71 deletions
diff --git a/meta/lib/patchtest/repo.py b/meta/lib/patchtest/repo.py
index d3788f466d..5f361ac500 100644
--- a/meta/lib/patchtest/repo.py
+++ b/meta/lib/patchtest/repo.py
@@ -11,6 +11,7 @@
11import os 11import os
12import utils 12import utils
13import logging 13import logging
14import git
14from patch import PatchTestPatch 15from patch import PatchTestPatch
15 16
16logger = logging.getLogger('patchtest') 17logger = logging.getLogger('patchtest')
@@ -21,15 +22,17 @@ class PatchTestRepo(object):
21 # prefixes used for temporal branches/stashes 22 # prefixes used for temporal branches/stashes
22 prefix = 'patchtest' 23 prefix = 'patchtest'
23 24
25
24 def __init__(self, patch, repodir, commit=None, branch=None): 26 def __init__(self, patch, repodir, commit=None, branch=None):
25 self._repodir = repodir 27 self._repodir = repodir
28 self._repo = git.Repo.init(repodir)
26 self._patch = PatchTestPatch(patch) 29 self._patch = PatchTestPatch(patch)
27 self._current_branch = self._get_current_branch() 30 self._current_branch = self._repo.active_branch.name
28 31
29 # targeted branch defined on the patch may be invalid, so make sure there 32 # targeted branch defined on the patch may be invalid, so make sure there
30 # is a corresponding remote branch 33 # is a corresponding remote branch
31 valid_patch_branch = None 34 valid_patch_branch = None
32 if self._patch.branch in self.upstream_branches(): 35 if self._patch.branch in self._repo.branches:
33 valid_patch_branch = self._patch.branch 36 valid_patch_branch = self._patch.branch
34 37
35 # Target Branch 38 # Target Branch
@@ -52,22 +55,19 @@ class PatchTestRepo(object):
52 55
53 self._workingbranch = "%s_%s" % (PatchTestRepo.prefix, os.getpid()) 56 self._workingbranch = "%s_%s" % (PatchTestRepo.prefix, os.getpid())
54 57
55 # create working branch 58 # create working branch. Use the '-B' flag so that we just
56 self._exec({'cmd': ['git', 'checkout', '-b', self._workingbranch, self._commit]}) 59 # check out the existing one if it's there
60 self._repo.git.execute(['git', 'checkout', '-B', self._workingbranch, self._commit])
57 61
58 self._patchmerged = False 62 self._patchmerged = False
59 63
60 # Check if patch can be merged using git-am 64 # Check if patch can be merged using git-am
61 self._patchcanbemerged = True 65 self._patchcanbemerged = True
62 try: 66 try:
63 self._exec({'cmd': ['git', 'am', '--keep-cr'], 'input': self._patch.contents}) 67 # Make sure to get the absolute path of the file
64 except utils.CmdException as ce: 68 self._repo.git.execute(['git', 'apply', '--check', os.path.abspath(self._patch.path)], with_exceptions=True)
65 self._exec({'cmd': ['git', 'am', '--abort']}) 69 except git.exc.GitCommandError as ce:
66 self._patchcanbemerged = False 70 self._patchcanbemerged = False
67 finally:
68 # if patch was applied, remove it
69 if self._patchcanbemerged:
70 self._exec({'cmd':['git', 'reset', '--hard', self._commit]})
71 71
72 # for debugging purposes, print all repo parameters 72 # for debugging purposes, print all repo parameters
73 logger.debug("Parameters") 73 logger.debug("Parameters")
@@ -97,78 +97,24 @@ class PatchTestRepo(object):
97 def canbemerged(self): 97 def canbemerged(self):
98 return self._patchcanbemerged 98 return self._patchcanbemerged
99 99
100 def _exec(self, cmds):
101 _cmds = []
102 if isinstance(cmds, dict):
103 _cmds.append(cmds)
104 elif isinstance(cmds, list):
105 _cmds = cmds
106 else:
107 raise utils.CmdException({'cmd':str(cmds)})
108
109 results = []
110 cmdfailure = False
111 try:
112 results = utils.exec_cmds(_cmds, self._repodir)
113 except utils.CmdException as ce:
114 cmdfailure = True
115 raise ce
116 finally:
117 if cmdfailure:
118 for cmd in _cmds:
119 logger.debug("CMD: %s" % ' '.join(cmd['cmd']))
120 else:
121 for result in results:
122 cmd, rc, stdout, stderr = ' '.join(result['cmd']), result['returncode'], result['stdout'], result['stderr']
123 logger.debug("CMD: %s RCODE: %s STDOUT: %s STDERR: %s" % (cmd, rc, stdout, stderr))
124
125 return results
126
127 def _get_current_branch(self, commit='HEAD'):
128 cmd = {'cmd':['git', 'rev-parse', '--abbrev-ref', commit]}
129 cb = self._exec(cmd)[0]['stdout']
130 if cb == commit:
131 logger.warning('You may be detached so patchtest will checkout to master after execution')
132 cb = 'master'
133 return cb
134
135 def _get_commitid(self, commit): 100 def _get_commitid(self, commit):
136 101
137 if not commit: 102 if not commit:
138 return None 103 return None
139 104
140 try: 105 try:
141 cmd = {'cmd':['git', 'rev-parse', '--short', commit]} 106 return self._repo.rev_parse(commit).hexsha
142 return self._exec(cmd)[0]['stdout'] 107 except Exception as e:
143 except utils.CmdException as ce: 108 print(f"Couldn't find commit {commit} in repo")
144 # try getting the commit under any remotes
145 cmd = {'cmd':['git', 'remote']}
146 remotes = self._exec(cmd)[0]['stdout']
147 for remote in remotes.splitlines():
148 cmd = {'cmd':['git', 'rev-parse', '--short', '%s/%s' % (remote, commit)]}
149 try:
150 return self._exec(cmd)[0]['stdout']
151 except utils.CmdException:
152 pass
153 109
154 return None 110 return None
155 111
156 def upstream_branches(self):
157 cmd = {'cmd':['git', 'branch', '--remotes']}
158 remote_branches = self._exec(cmd)[0]['stdout']
159
160 # just get the names, without the remote name
161 branches = set(branch.split('/')[-1] for branch in remote_branches.splitlines())
162 return branches
163
164 def merge(self): 112 def merge(self):
165 if self._patchcanbemerged: 113 if self._patchcanbemerged:
166 self._exec({'cmd': ['git', 'am', '--keep-cr'], 114 self._repo.git.execute(['git', 'am', '--keep-cr', os.path.abspath(self._patch.path)])
167 'input': self._patch.contents,
168 'updateenv': {'PTRESOURCE':self._patch.path}})
169 self._patchmerged = True 115 self._patchmerged = True
170 116
171 def clean(self): 117 def clean(self):
172 self._exec({'cmd':['git', 'checkout', '%s' % self._current_branch]}) 118 self._repo.git.execute(['git', 'checkout', self._current_branch])
173 self._exec({'cmd':['git', 'branch', '-D', self._workingbranch]}) 119 self._repo.git.execute(['git', 'branch', '-D', self._workingbranch])
174 self._patchmerged = False 120 self._patchmerged = False