[PATCH 2 of 3] subrepo: allow git subrepos to push and merge
Augie Fackler
durin42 at gmail.com
Sun Nov 14 04:39:49 UTC 2010
On Nov 11, 2010, at 1:43 PM, Eric Eisner wrote:
> # HG changeset patch
> # User Eric Eisner <ede at mit.edu>
> # Date 1289503448 18000
> # Node ID 6485c19a9601d37ff5a55385e0769ab93cf471cf
> # Parent ccc59ab604a8160d44847754f8b48dedb25d2f16
> subrepo: allow git subrepos to push and merge
>
> (master branch only)
>
> gitsubrepo based on patch from David Soria Parra:
> http://bitbucket.org/segv/davids-poor-git-subrepo-attempt/
>
> diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
> --- a/mercurial/subrepo.py
> +++ b/mercurial/subrepo.py
> @@ -612,7 +612,10 @@ class gitsubrepo(object):
> err = err.read().strip()
>
> if err:
> - raise util.Abort(err)
> + # TODO: differentiate between failing and succeeding cases
> + # merge fetch and push all print to stderr normally...
> + if 'merge' not in commands:
> + raise util.Abort(err)
> # we have to wait for the child to exit to avoid race condition.
> p.wait()
> return retdata, p.returncode
> @@ -626,19 +629,21 @@ class gitsubrepo(object):
>
> def _fetch(self, source, revision):
> if not os.path.exists('%s/.git' % self._path):
> + self._ui.status(_('cloning subrepo %s\n') % self._path)
> self._gitnodir(['clone', source, self._path])
> if self._githavelocally(revision):
> return
> self._ui.status(_('pulling subrepo %s\n') % self._path)
> - self._gitcommand(['fetch', '--all', source])
> + self._gitcommand(['fetch', '--all', '-q'])
> if not self._githavelocally(revision):
> raise util.Abort(_("revision %s does not exist in subrepo %s\n") %
> - (revision, source))
> + (revision, self._path))
>
> def dirty(self):
> if self._state[1] != self._gitstate(): # version checked out changed?
> return True
> # check for staged changes or modified files; ignore untracked files
> + # docs say --porcelain flag is future-proof format
> changed = self._gitcommand(['status', '--porcelain',
> '--untracked-files=no'])
> return bool(changed.strip())
> @@ -653,14 +658,41 @@ class gitsubrepo(object):
> cmd = ['commit', '-a', '-m', text]
> if user:
> cmd += ['--author', user]
> - # TODO: git's date parser silently ignores when seconds < 1e9
> if date:
> - cmd += ['--date', '%s %s' % date]
> + # git's date parser silently ignores when seconds < 1e9
> + # convert to ISO8601
> + cmd += ['--date', util.datestr(date, '%Y-%m-%dT%H:%M:%S %1%2')]
Curious, why isn't this hunk part of the previous patch? Not a big deal unless others feel strongly.
> self._gitcommand(cmd)
> # make sure commit works otherwise HEAD might not exist under certain
> # circumstances
> return self._gitstate()
>
> + def merge(self, state):
> + source, revision, kind = state
> + self._fetch(source, revision)
> + base = self._gitcommand(['merge-base', revision, self._state[1]])
> + if base.startswith(revision):
> + self.get(state)
> + elif not base.startswith(self._state[1]):
> + self._gitcommand(['merge', '--no-commit', revision])
> +
> + def remove(self):
> + if self.dirty():
> + self._ui.warn(_('not removing repo %s because '
> + 'it has changes.\n') % self._path)
> + return
> + self._ui.note(_('removing subrepo %s\n') % self._path)
> + shutil.rmtree(self._ctx.repo.join(self._path))
> +
> + def push(self, force):
> + cmd = ['push']
> + if force:
> + cmd.append('--force')
> + # as subrepos have no notion of "where to push to" we
> + # assume origin master. This is git's default
> + self._gitcommand(cmd + ['origin', 'master', '-q'])
> + return True
> +
> types = {
> 'hg': hgsubrepo,
> 'svn': svnsubrepo,
> diff --git a/tests/test-subrepo-git.t b/tests/test-subrepo-git.t
> --- a/tests/test-subrepo-git.t
> +++ b/tests/test-subrepo-git.t
> @@ -57,3 +57,101 @@ record a new commit from upstream
> path s
> source ../gitroot
> revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
> +
> +make $GITROOT pushable, by replacing it with a clone with nothing checked out
> +
> + $ cd ..
> + $ git clone gitroot gitrootbare --bare -q
> + $ rm -rf gitroot
> + $ mv gitrootbare gitroot
> +
> +clone root, make local change
> +
> + $ cd t
> + $ hg clone . ../ta
> + updating to branch default
> + cloning subrepo $TESTTMP/ta/s
> + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
> + $ cd ../ta
> + $ hg debugsub
> + path s
> + source ../gitroot
> + revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
> +
> + $ echo ggg >> s/g
> + $ hg commit -m ggg
> + committing subrepository $TESTTMP/ta/s
> + $ hg debugsub
> + path s
> + source ../gitroot
> + revision 79695940086840c99328513acbe35f90fcd55e57
> +
> +clone root separately, make different local change
> +
> + $ cd ../t
> + $ hg clone . ../tb
> + updating to branch default
> + cloning subrepo $TESTTMP/tb/s
> + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
> + $ cd ../tb
> + $ hg debugsub
> + path s
> + source ../gitroot
> + revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
> +
> + $ cd s
> + $ echo f > f
> + $ git add f
> + $ cd ..
> +
> + $ hg commit -m f
> + committing subrepository $TESTTMP/tb/s
> + $ hg debugsub
> + path s
> + source ../gitroot
> + revision aa84837ccfbdfedcdcdeeedc309d73e6eb069edc
> +
> +user b push changes
> +
> + $ hg push
> + pushing to $TESTTMP/t
> + searching for changes
> + adding changesets
> + adding manifests
> + adding file changes
> + added 1 changesets with 1 changes to 1 files
> +
> +user a pulls, merges, commits
> +
> + $ cd ../ta
> + $ hg pull
> + pulling from $TESTTMP/t
> + searching for changes
> + adding changesets
> + adding manifests
> + adding file changes
> + added 1 changesets with 1 changes to 1 files (+1 heads)
> + (run 'hg heads' to see heads, 'hg merge' to merge)
> + $ hg merge
> + pulling subrepo $TESTTMP/ta/s
> + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
> + (branch merge, don't forget to commit)
> + $ cat s/f
> + f
> + $ cat s/g
> + g
> + gg
> + ggg
> + $ hg commit -m 'merge'
> + committing subrepository $TESTTMP/ta/s
> + $ hg debugsub
> + path s
> + source ../gitroot
> + revision f47b465e1bce645dbf37232a00574aa1546ca8d3
> + $ hg push
> + pushing to $TESTTMP/t
> + searching for changes
> + adding changesets
> + adding manifests
> + adding file changes
> + added 2 changesets with 2 changes to 1 files
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
More information about the Mercurial-devel
mailing list