From: Markus Lehtonen Date: Tue, 12 Jun 2012 07:42:41 +0000 (+0300) Subject: rpm: support squashing commits in patch generation X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fa9e87adb602e45661fbabbbc7ace33f4b87088e;p=tools%2Fgit-buildpackage.git rpm: support squashing commits in patch generation Implements an option for git-buildpackage-rpm and gbp-pq to squash commits (from upstream) up to certain tree-ish into one monolithic diff. Useful e.g. if you wan't to auto-generate a stable update patch. The new format of the cmdline option filename is commit-ish followed by (optionally) a colon and the desired diff filename base. Suffix '.diff' is added by GBP. Magic word 'HEAD' translates to the end-commit when given as the squash-point. This allows one to configure gbp to always squash all commits into one monolithic diff. Signed-off-by: Markus Lehtonen --- diff --git a/gbp-rpm.conf b/gbp-rpm.conf index 2e31a685..27f80257 100644 --- a/gbp-rpm.conf +++ b/gbp-rpm.conf @@ -26,6 +26,8 @@ #spec-file = gbp.spec # Compress auto-generated patches #patch-export-compress=100k +# Squash commits until certain tree-ish into one diff +#patch-export-squash-until = stable-updates:stable # Export patches with numbering in filenames #patch-numbers = False @@ -108,7 +110,7 @@ ### [gbp-pq-rpm] # Name of the patch-queue / development branch -pq-branch = %(branch)s-devel +#pq-branch = %(branch)s-devel ### ### Options only affecting gbp-clone diff --git a/gbp/config.py b/gbp/config.py index 5a5f382a..dd71c427 100644 --- a/gbp/config.py +++ b/gbp/config.py @@ -551,6 +551,7 @@ class GbpOptionParserRpm(GbpOptionParser): 'rpmbuild-buildrootdir' : 'BUILDROOT', 'patch-export' : 'False', 'patch-export-compress' : '0', + 'patch-export-squash-until' : '', 'pristine-tarball-name' : 'auto', 'orig-prefix' : 'auto', } ) @@ -573,6 +574,11 @@ class GbpOptionParserRpm(GbpOptionParser): "Create patches between upstream and export-treeish, default is '%(patch-export)s'", 'patch-export-compress': "Compress (auto-generated) patches larger than given number of bytes, 0 never compresses, default is '%(patch-export-compress)s'", + 'patch-export-squash-until': + ("Squash commits (from upstream) until given tree-ish " + "into one big diff, format is " + "'[:]'. " + "Default is '%(patch-export-squash-until)s'"), 'pristine-tarball-name': "Filename to record to pristine-tar, set to 'auto' to not mangle the file name, default is '%(pristine-tarball-name)s'", 'orig-prefix': diff --git a/gbp/scripts/buildpackage_rpm.py b/gbp/scripts/buildpackage_rpm.py index 70e09402..3ac78b4e 100755 --- a/gbp/scripts/buildpackage_rpm.py +++ b/gbp/scripts/buildpackage_rpm.py @@ -360,6 +360,7 @@ def parse_args(argv, prefix): help="only export packaging files, don't build") export_group.add_boolean_config_file_option("patch-export", dest="patch_export") export_group.add_config_file_option("patch-export-compress", dest="patch_export_compress") + export_group.add_config_file_option("patch-export-squash-until", dest="patch_export_squash_until") export_group.add_boolean_config_file_option(option_name="patch-numbers", dest="patch_numbers") options, args = parser.parse_args(args) diff --git a/gbp/scripts/pq_rpm.py b/gbp/scripts/pq_rpm.py index 796ea34b..228fa1e4 100755 --- a/gbp/scripts/pq_rpm.py +++ b/gbp/scripts/pq_rpm.py @@ -28,7 +28,7 @@ import gzip import subprocess from gbp.config import (GbpOptionParserRpm, GbpOptionGroup) from gbp.rpm.git import (GitRepositoryError, RpmGitRepository) -from gbp.git import GitModifier +from gbp.git.modifier import GitModifier, GitTz from gbp.command_wrappers import (Command, GitCommand, RunAtCommand, CommandExecFailed) from gbp.errors import GbpError @@ -60,7 +60,7 @@ def compress_patches(patches, compress_size=0): return ret_patches -def generate_patches(repo, start, end, outdir, options): +def generate_patches(repo, start, squash, end, outdir, options): """ Generate patch files from git """ @@ -71,6 +71,7 @@ def generate_patches(repo, start, end, outdir, options): if not repo.has_treeish(treeish): raise GbpError('%s not a valid tree-ish' % treeish) + start_sha1 = repo.rev_parse("%s^0" % start) try: end_commit = end end_commit_sha1 = repo.rev_parse("%s^0" % end_commit) @@ -84,6 +85,26 @@ def generate_patches(repo, start, end, outdir, options): 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)) + # Squash commits, if requested + if squash[0]: + if squash[0] == 'HEAD': + squash[0] = end_commit + squash_sha1 = repo.rev_parse("%s^0" % squash[0]) + if start_sha1 != squash_sha1: + if not squash_sha1 in repo.get_commits(start, end_commit): + raise GbpError("Given squash point '%s' not in the history " + "of end commit '%s'" % (squash[0], end_commit)) + # Shorten SHA1s + squash_sha1 = repo.rev_parse(squash_sha1, short=7) + start_sha1 = repo.rev_parse(start_sha1, short=7) + gbp.log.info("Squashing commits %s..%s into one monolithic diff" % + (start_sha1, squash_sha1)) + patch_fn = format_diff(outdir, squash[1], repo, + start_sha1, squash_sha1) + if patch_fn: + patches.append(patch_fn) + start = squash_sha1 + # Generate patches for commit in reversed(repo.get_commits(start, end_commit)): info = repo.get_commit_info(commit) @@ -132,10 +153,16 @@ def update_patch_series(repo, spec, start, end, options): """ Export patches to packaging directory and update spec file accordingly. """ + squash = options.patch_export_squash_until.split(':', 1) + if len(squash) == 1: + squash.append(None) + else: + squash[1] += '.diff' + # Unlink old patch files and generate new patches rm_patch_files(spec) - patches, _commands = generate_patches(repo, start, end, + patches, _commands = generate_patches(repo, start, squash, end, spec.specdir, options) spec.update_patches(patches) spec.write_spec_file() @@ -388,6 +415,7 @@ def main(argv): "of head of patch-queue branch", metavar="TREEISH") parser.add_config_file_option("patch-export-compress", dest="patch_export_compress") + parser.add_config_file_option("patch-export-squash-until", dest="patch_export_squash_until") (options, args) = parser.parse_args(argv) gbp.log.setup(options.color, options.verbose)