summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Lehtonen <markus.lehtonen@linux.intel.com>2012-08-07 16:30:36 +0300
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>2012-09-18 19:02:51 +0300
commitb24412b40ec93927f90ee5472bb7771ee1cc0631 (patch)
treebc6f7fa7312339ca7854beb7b82f805064cf97e8
parent85b63cfeaf4e8de9a58c1cf7958ab0f3bb7548db (diff)
downloadgit-buildpackage-b24412b40ec93927f90ee5472bb7771ee1cc0631.tar.gz
git-buildpackage-b24412b40ec93927f90ee5472bb7771ee1cc0631.tar.bz2
git-buildpackage-b24412b40ec93927f90ee5472bb7771ee1cc0631.zip
rpm-pq: rework patch generation code, again
Get rid of text file parsing and regenerating of patches. Instead, commits are examined, filtered and generated one-by-one. Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com>
-rwxr-xr-xgbp/scripts/pq_rpm.py181
1 files changed, 96 insertions, 85 deletions
diff --git a/gbp/scripts/pq_rpm.py b/gbp/scripts/pq_rpm.py
index 296cd1a2..e2bc78d7 100755
--- a/gbp/scripts/pq_rpm.py
+++ b/gbp/scripts/pq_rpm.py
@@ -39,76 +39,85 @@ from gbp.scripts.common.pq import (is_pq_branch, pq_branch_name, pq_branch_base,
switch_to_pq_branch, apply_single_patch,
apply_and_commit_patch, drop_pq)
-def write_patch(patch, out_dir, patch_numbers=True, compress_size=0, ignore_regex=None):
+def compress_patches(patches, compress_size=0):
"""
- Write the patch exported by 'git-format-patch' to it's final location
- (as specified in the commit)
+ Rename and/or compress patches
"""
- tmp_path = patch + ".gbp"
+ ret_patches = []
+ for num, patch in enumerate(patches):
+ # Compress if patch file is larger than "threshold" value
+ if compress_size and os.path.getsize(patch) > compress_size:
+ gbp.log.debug("Compressing %s" % os.path.basename(patch))
+ subprocess.Popen(['gzip', '-n', patch]).communicate()
+ patch += ".gz"
- old = file(patch, 'r')
- tmp = file(tmp_path, 'w')
- # Skip the first From <sha>... line
- old.readline()
- for line in old:
- if ignore_regex and re.match(ignore_regex, line):
- gbp.log.debug("Ignoring patch %s, matches ignore-regex" % patch)
- old.close()
- tmp.close()
- os.unlink(patch)
- os.unlink(tmp_path)
- return
- elif (line.startswith("diff --git a/") or
- line.startswith("---")):
- tmp.write(line)
- break;
- tmp.write(line)
-
- # Write the rest of the file
- tmp.writelines(old)
- tmp.close()
- old.close()
-
- new_name = os.path.basename(patch)
- if not patch_numbers:
- patch_re = re.compile("[0-9]+-(?P<name>.+)")
- m = patch_re.match(new_name)
- if m:
- new_name = m.group('name')
-
- # Compress if patch file is larger than "threshold" value
- if compress_size and os.path.getsize(tmp_path) > compress_size:
- dst_path = os.path.join(out_dir, new_name + '.gz')
- gbp.log.debug("Compressing %s to %s" % (tmp_path, dst_path))
- f_new = open(dst_path, 'w+')
- subprocess.Popen(['gzip', '-n', '-c', tmp_path], stdout=f_new).communicate()
- f_new.close()
- else:
- dst_path = os.path.join(out_dir, new_name)
- gbp.log.debug("Moving %s to %s" % (tmp_path, dst_path))
- shutil.copy2(tmp_path, dst_path)
+ ret_patches.append(os.path.basename(patch))
- os.unlink(tmp_path)
- os.unlink(patch)
+ return ret_patches
- return dst_path
-
-def write_diff_file(repo, start, end, diff_filename):
+def write_diff_file(repo, diff_filename, start, end):
"""
Write diff between two tree-ishes into a file
"""
try:
diff = repo.diff(start, end)
- diff_file = open(diff_filename, 'w+')
- diff_file.writelines(diff)
- diff_file.close()
+ if diff:
+ diff_file = open(diff_filename, 'w+')
+ diff_file.writelines(diff)
+ diff_file.close()
+ return diff_filename
+ else:
+ gbp.log.debug("I won't generate empty diff %s" % diff_filename)
+ return None
except IOError:
raise GbpError, "Unable to create diff file"
-def generate_git_patches(repo, start, squash_point, end, squash_diff_name,
- outdir):
+def patch_content_filter(f_in, f_out):
+ # Skip the first line that contains commits SHA2
+ f_in.readline()
+ f_out.writelines(f_in)
+
+
+def patch_fn_filter(commit_info, patch_number=None, ignore_regex=None,
+ topic_regex=None):
+ """
+ Create a patch filename, return None if patch is to be ignored.
+ """
+ suffix = ".patch"
+ topic = ""
+ # Filter based on subject
+ if ignore_regex and re.match(ignore_regex, commit_info['subject']):
+ gbp.log.debug("Ignoring commit %s, subject matches ignore-regex" %
+ commit_info['id'])
+ return None
+ # Parse commit message
+ for line in commit_info['body'].splitlines():
+ if ignore_regex and re.match(ignore_regex, line):
+ gbp.log.debug("Ignoring commit %s, commit message matches "\
+ "ignore-regex" % commit_info['id'])
+ return None
+ if topic_regex:
+ match = re.match(topic_regex, line, flags=re.I)
+ if match:
+ gbp.log.debug("Topic %s found for %s" %
+ (match.group['topic'], commit_info['id']))
+ topic = match.group['topic'] + os.path.sep
+
+ filename = topic
+ if patch_number is not None:
+ filename += "%04d-" % patch_number
+ filename += commit_info['patchname']
+ # Truncate filename
+ filename = filename[:64-len(suffix)]
+ filename += suffix
+
+ return filename
+
+
+def generate_patches(repo, start, squash_point, end, squash_diff_name,
+ outdir, options):
"""
Generate patch files from git
"""
@@ -131,11 +140,11 @@ def generate_git_patches(repo, start, squash_point, end, squash_diff_name,
if repo.get_merge_base(start_sha1, end_commit_sha1) != start_sha1:
raise GbpError, "Start commit '%s' not an ancestor of end " \
"commit '%s'" % (start, end_commit)
+ rev_list = reversed(repo.get_commits(start, end_commit))
# Squash commits, if requested
if squash_point:
squash_sha1 = repo.rev_parse("%s^0" % squash_point)
if start_sha1 != squash_sha1:
- rev_list = repo.get_commits(start, end_commit)
if not squash_sha1 in rev_list:
raise GbpError, "Given squash point '%s' not found in the " \
"history of end commit '%s'" % \
@@ -148,24 +157,41 @@ def generate_git_patches(repo, start, squash_point, end, squash_diff_name,
diff_filename = squash_diff_name + ".diff"
else:
diff_filename = '%s-to-%s.diff' % (start_sha1, squash_sha1)
- gbp.log.info("Squashing commits %s..%s into one monolithic '%s'" %
- (start_sha1, squash_sha1, diff_filename))
- diff_filepath = os.path.join(outdir, diff_filename)
- write_diff_file(repo, start_sha1, squash_sha1, diff_filepath)
- patches.append(diff_filepath)
+ gbp.log.info("Squashing commits %s..%s into one monolithic "\
+ "'%s'" % (start_sha1, squash_sha1, diff_filename))
+ diff_filepath = os.path.join(outdir, diff_filename)
+ if write_diff_file(repo, diff_filepath, start_sha1, squash_sha1):
+ patches.append(diff_filepath)
start = squash_sha1
# Generate patches
- patches.extend(repo.format_patches(start, end_commit, outdir))
+ patch_num = 1 if options.patch_numbers else None
+ for commit in rev_list:
+ info = repo.get_commit_info(commit)
+ patch_fn = patch_fn_filter(info, patch_num,
+ options.patch_export_ignore_regex)
+ if patch_fn:
+ patch_fn = repo.format_patch(commit,
+ os.path.join(outdir, patch_fn),
+ filter_fn=patch_content_filter,
+ signature=False)
+ if patch_fn:
+ patches.append(patch_fn)
+ if options.patch_numbers:
+ patch_num += 1
+
# Generate diff to the tree-ish object
if end_commit != end:
diff_filename = '%s.diff' % end
gbp.log.info("Generating '%s' (%s..%s)" % \
(diff_filename, end_commit, end))
diff_filepath = os.path.join(outdir, diff_filename)
- write_diff_file(repo, end_commit, end, diff_filepath)
- patches.append(diff_filepath)
+ if write_diff_file(repo, diff_filepath, end_commit, end):
+ patches.append(diff_filepath)
+
+ # Compress
+ patches = compress_patches(patches, options.patch_export_compress)
return patches
@@ -179,12 +205,6 @@ def update_patch_series(repo, spec, start, end, options):
squash = options.patch_export_squash_until.split(':', 1)
squash_point = squash[0]
squash_name = squash[1] if len(squash) > 1 else ""
- patches = generate_git_patches(repo,
- start,
- squash_point,
- end,
- squash_name,
- tmpdir)
# Remove all old patches from packaging dir
for n, p in spec.patches.iteritems():
@@ -199,21 +219,12 @@ def update_patch_series(repo, spec, start, end, options):
else:
gbp.log.debug("%s does not exist." % f)
- # Filter "vanilla" patches through write_patch()
- filenames = []
- if patches:
- gbp.log.debug("Regenerating patch series in '%s'." % spec.specdir)
- for patch in patches:
- patch_file = write_patch(patch,
- spec.specdir,
- options.patch_numbers,
- options.patch_export_compress,
- options.patch_export_ignore_regex)
- if patch_file != None:
- filenames.append(os.path.basename(patch_file))
-
- spec.update_patches(filenames)
- spec.write_spec_file()
+ patches = generate_patches(repo, start, squash_point, end, squash_name,
+ spec.specdir, options)
+
+ filenames = [os.path.basename(patch) for patch in patches]
+ spec.update_patches(filenames)
+ spec.write_spec_file()
def export_patches(repo, branch, options):