diff options
-rw-r--r-- | morphlib/git.py | 1 | ||||
-rw-r--r-- | morphlib/plugins/branch_and_merge_plugin.py | 100 | ||||
-rw-r--r-- | tests.branching/merge-explicitly-named-repos.stdout | 1 | ||||
-rwxr-xr-x | tests.branching/merge.script (renamed from tests.branching/merge-explicitly-named-repos.script) | 27 | ||||
-rwxr-xr-x | tests.branching/workflow.script | 7 |
5 files changed, 103 insertions, 33 deletions
diff --git a/morphlib/git.py b/morphlib/git.py index 70915770..0a4b01f4 100644 --- a/morphlib/git.py +++ b/morphlib/git.py @@ -150,7 +150,6 @@ def checkout_ref(runcmd, gitdir, ref): '''Checks out a specific ref/SHA1 in a git working tree.''' runcmd(['git', 'checkout', ref], cwd=gitdir) - def reset_workdir(runcmd, gitdir): '''Removes any differences between the current commit ''' '''and the status of the working directory''' diff --git a/morphlib/plugins/branch_and_merge_plugin.py b/morphlib/plugins/branch_and_merge_plugin.py index d44ccacc..c2401631 100644 --- a/morphlib/plugins/branch_and_merge_plugin.py +++ b/morphlib/plugins/branch_and_merge_plugin.py @@ -49,7 +49,7 @@ class BranchAndMergePlugin(cliapp.Plugin): self.app.add_subcommand('show-branch-root', self.show_branch_root, arg_synopsis='') self.app.add_subcommand('merge', self.merge, - arg_synopsis='BRANCH REPO...') + arg_synopsis='BRANCH') self.app.add_subcommand('edit', self.edit, arg_synopsis='SYSTEM STRATUM [CHUNK]') self.app.add_subcommand('build', self.build, @@ -536,24 +536,92 @@ class BranchAndMergePlugin(cliapp.Plugin): self.print_changelog('The following changes were made but have not ' 'been comitted') + def merge_repo(self, name, from_dir, from_branch, to_dir, to_branch, + is_morphs_repo = False): + '''Merge changes for a system branch in a specific repository''' + + if self.get_uncommitted_changes(from_dir) != []: + raise cliapp.AppException('repository %s has uncommitted ' + 'changes', name) + # repo must be made into a URL to avoid ':' in pathnames confusing git + from_url = urlparse.urljoin('file://', from_dir) + if is_morphs_repo: + # We use --no-commit in this case, so we can then revert the refs + # that were changed for the system branch in the merge commit + self.app.runcmd(['git', 'pull', '--no-commit', '--no-ff', from_url, + from_branch], cwd=to_dir) + else: + self.app.runcmd(['git', 'pull', '--no-ff', from_url, from_branch], + cwd=to_dir) + def merge(self, args): - '''Merge specified repositories from another system branch.''' + '''Pull and merge changes from a system branch into the current one.''' - if len(args) < 2: - raise cliapp.AppException('morph merge must get a branch name ' - 'and some repo names as arguments') + if len(args) != 1: + raise cliapp.AppException('morph merge requires a system branch ' + 'name as its argument') workspace = self.deduce_workspace() - other_branch, other_branch_dir = \ - args[0], self.find_system_branch(workspace, args[0]) - this_branch, this_branch_dir = self.deduce_system_branch() - - for repo in args[1:]: - pull_dir = self.find_repository(other_branch_dir, repo) - pull_url = urlparse.urljoin('file://', pull_dir) - repo_dir = self.find_repository(this_branch_dir, repo) - self.app.runcmd(['git', 'pull', pull_url, other_branch], - cwd=repo_dir) + from_branch = args[0] + from_branch_dir = self.find_system_branch(workspace, from_branch) + to_branch, to_branch_dir = self.deduce_system_branch() + + root_repo = self.get_branch_config(from_branch_dir, 'branch.root') + other_root_repo = self.get_branch_config(to_branch_dir, 'branch.root') + if root_repo != other_root_repo: + raise cliapp.AppException('branches do not share a root ' + 'repository : %s vs %s' % + (root_repo, other_root_repo)) + + def _merge_chunk(ci): + from_repo = self.find_repository(from_branch_dir, ci['repo']) + to_repo = self.make_repository_available( + to_branch, to_branch_dir, ci['repo'], to_branch) + self.merge_repo( + ci['repo'], from_repo, from_branch, to_repo, to_branch) + + def _merge_stratum(si): + if si['repo'] == root_repo: + to_repo = to_root_dir + else: + from_repo = self.find_repository(from_branch_dir, si['repo']) + to_repo = self.make_repository_available( + to_branch, to_branch_dir, si['repo'], to_branch) + self.merge_repo( + si['repo'], from_repo, from_branch, to_repo, to_branch, + is_morphs_repo=True) + # We will do a merge commit in this repo later on + morphs_repo_list.add(to_repo) + + stratum = self.load_morphology(to_repo, si['morph']) + for ci in stratum['chunks']: + if ci['ref'] == from_branch: + _merge_chunk(ci) + ci['ref'] = to_branch + self.save_morphology(to_repo, si['morph'], stratum) + + from_root_dir = self.find_repository(from_branch_dir, root_repo) + to_root_dir = self.find_repository(to_branch_dir, root_repo) + self.app.runcmd(['git', 'checkout', to_branch], cwd=to_root_dir) + self.merge_repo(root_repo, from_root_dir, from_branch, to_root_dir, + to_branch, is_morphs_repo = True) + morphs_repo_list = set([to_root_dir]) + + for f in glob.glob(os.path.join(to_root_dir, '*.morph')): + name = f[:-len('.morph')] + morphology = self.load_morphology(to_root_dir, name) + + if morphology['kind'] == 'system': + for si in morphology['strata']: + if si['ref'] == from_branch: + _merge_stratum(si) + si['ref'] = to_branch + self.save_morphology(to_root_dir, name, morphology) + + for repo in morphs_repo_list: + msg = "Merge system branch '%s'" % from_branch + self.app.runcmd(['git', 'commit', '--all', '--message="%s"' % msg], + cwd=repo) def build(self, args): if len(args) != 1: @@ -674,7 +742,7 @@ class BranchAndMergePlugin(cliapp.Plugin): except: return None - def get_uncommitted_changes(self, repo_dir, env): + def get_uncommitted_changes(self, repo_dir, env={}): status = self.app.runcmd(['git', 'status', '--porcelain'], cwd=repo_dir, env=env) changes = [] diff --git a/tests.branching/merge-explicitly-named-repos.stdout b/tests.branching/merge-explicitly-named-repos.stdout deleted file mode 100644 index cd2122c4..00000000 --- a/tests.branching/merge-explicitly-named-repos.stdout +++ /dev/null @@ -1 +0,0 @@ -newfile.txt diff --git a/tests.branching/merge-explicitly-named-repos.script b/tests.branching/merge.script index 7dfd5780..7c433519 100755 --- a/tests.branching/merge-explicitly-named-repos.script +++ b/tests.branching/merge.script @@ -14,34 +14,37 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -# Check that "morph merge" merges explicitly named repositories. - +# Check that "morph merge" merges a system branch into master set -eu - # Create system branch. cd "$DATADIR/workspace" "$SRCDIR/scripts/test-morph" init -"$SRCDIR/scripts/test-morph" branch baserock:morphs newbranch +"$SRCDIR/scripts/test-morph" branch baserock:morphs baserock/newbranch # Make a change to a chunk. "$SRCDIR/scripts/test-morph" edit hello-system hello-stratum hello -cd newbranch/baserock:hello +cd baserock/newbranch/baserock:hello touch newfile.txt git add newfile.txt git commit -m foo --quiet -# Merge changes to a new system branch. +# Commit in morphs repo +cd ../baserock:morphs +git commit --all --quiet -m "Update morph refs for baserock/newbranch" + +# Merge changes back to master cd "$DATADIR/workspace" -"$SRCDIR/scripts/test-morph" branch baserock:morphs otherbranch -cd otherbranch -"$SRCDIR/scripts/test-morph" edit hello-system hello-stratum hello -"$SRCDIR/scripts/test-morph" merge newbranch baserock:hello +"$SRCDIR/scripts/test-morph" checkout baserock:morphs master +cd master +"$SRCDIR/scripts/test-morph" merge baserock/newbranch # Check results. cd baserock:hello git status --short # make sure all changes are committed -ls newfile.txt # make sure the new file is there +[ -e newfile.txt ] # make sure the new file is there +# Make sure all refs to the merged branch have gone. +cd ../baserock:morphs +! grep "\"ref\": \"baserock/newbranch\"" *.morph diff --git a/tests.branching/workflow.script b/tests.branching/workflow.script index cb79c3c5..68da4f4a 100755 --- a/tests.branching/workflow.script +++ b/tests.branching/workflow.script @@ -30,9 +30,10 @@ echo > README yoyoyo git add README git commit -m "Fix README, yo!" --quiet +cd ../baserock:morphs +git commit --quiet --all -m "Commit changes for system branch" + cd "$DATADIR/workspace" "$SRCDIR/scripts/test-morph" checkout baserock:morphs master cd master -"$SRCDIR/scripts/test-morph" edit hello-system hello-stratum hello -"$SRCDIR/scripts/test-morph" merge me/readme-fix baserock:hello - +"$SRCDIR/scripts/test-morph" merge me/readme-fix |