[PATCH 2 of 3] subrepo: allow git subrepos to push and merge

Augie Fackler durin42 at gmail.com
Sat Nov 13 22:39:49 CST 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