##// END OF EJS Templates
subrepo: support for adding a git subrepo...
Eric Eisner -
r12992:2b73a327 default
parent child Browse files
Show More
@@ -0,0 +1,58 b''
1 $ "$TESTDIR/hghave" git || exit 80
2
3 make git commits repeatable
4
5 $ GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
6 $ GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
7 $ GIT_AUTHOR_DATE='1234567891 +0000'; export GIT_AUTHOR_DATE
8 $ GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME
9 $ GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL
10 $ GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE
11
12 root hg repo
13
14 $ hg init t
15 $ cd t
16 $ echo a > a
17 $ hg add a
18 $ hg commit -m a
19 $ cd ..
20
21 new external git repo
22
23 $ mkdir gitroot
24 $ cd gitroot
25 $ git init -q
26 $ echo g > g
27 $ git add g
28 $ git commit -q -m g
29
30 add subrepo clone
31
32 $ cd ../t
33 $ echo 's = [git]../gitroot' > .hgsub
34 $ git clone -q ../gitroot s
35 $ hg add .hgsub
36 $ hg commit -m 'new git subrepo'
37 committing subrepository $TESTTMP/t/s
38 $ hg debugsub
39 path s
40 source ../gitroot
41 revision da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
42
43 record a new commit from upstream
44
45 $ cd ../gitroot
46 $ echo gg >> g
47 $ git commit -q -a -m gg
48
49 $ cd ../t/s
50 $ git pull -q
51
52 $ cd ..
53 $ hg commit -m 'update git subrepo'
54 committing subrepository $TESTTMP/t/s
55 $ hg debugsub
56 path s
57 source ../gitroot
58 revision 126f2a14290cd5ce061fdedc430170e8d39e1c5a
@@ -5,7 +5,7 b''
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import errno, os, re, xml.dom.minidom, shutil, urlparse, posixpath
8 import errno, os, re, xml.dom.minidom, shutil, subprocess, urlparse, posixpath
9 from i18n import _
9 from i18n import _
10 import config, util, node, error, cmdutil
10 import config, util, node, error, cmdutil
11 hg = None
11 hg = None
@@ -576,7 +576,87 b' class svnsubrepo(abstractsubrepo):'
576 return self._svncommand(['cat'], name)
576 return self._svncommand(['cat'], name)
577
577
578
578
579 class gitsubrepo(object):
580 def __init__(self, ctx, path, state):
581 # TODO add git version check.
582 self._state = state
583 self._ctx = ctx
584 self._path = ctx._repo.wjoin(path)
585 self._ui = ctx._repo.ui
586
587 def _gitcommand(self, commands):
588 return self._gitdir(commands)[0]
589
590 def _gitdir(self, commands):
591 commands = ['--no-pager', '--git-dir=%s/.git' % self._path,
592 '--work-tree=%s' % self._path] + commands
593 return self._gitnodir(commands)
594
595 def _gitnodir(self, commands):
596 """Calls the git command
597
598 The methods tries to call the git command. versions previor to 1.6.0
599 are not supported and very probably fail.
600 """
601 cmd = ['git'] + commands
602 cmd = [util.shellquote(arg) for arg in cmd]
603 cmd = util.quotecommand(' '.join(cmd))
604
605 # print git's stderr, which is mostly progress and useful info
606 p = subprocess.Popen(cmd, shell=True, bufsize=-1,
607 close_fds=(os.name == 'posix'),
608 stdout=subprocess.PIPE)
609 retdata = p.stdout.read()
610 # wait for the child to exit to avoid race condition.
611 p.wait()
612
613 if p.returncode != 0:
614 # there are certain error codes that are ok
615 command = None
616 for arg in commands:
617 if not arg.startswith('-'):
618 command = arg
619 break
620 if command == 'cat-file':
621 return retdata, p.returncode
622 if command in ('commit', 'status') and p.returncode == 1:
623 return retdata, p.returncode
624 # for all others, abort
625 raise util.Abort('git %s error %d' % (command, p.returncode))
626
627 return retdata, p.returncode
628
629 def _gitstate(self):
630 return self._gitcommand(['rev-parse', 'HEAD']).strip()
631
632 def _githavelocally(self, revision):
633 out, code = self._gitdir(['cat-file', '-e', revision])
634 return code == 0
635
636 def dirty(self):
637 if self._state[1] != self._gitstate(): # version checked out changed?
638 return True
639 # check for staged changes or modified files; ignore untracked files
640 # docs say --porcelain flag is future-proof format
641 changed = self._gitcommand(['status', '--porcelain',
642 '--untracked-files=no'])
643 return bool(changed.strip())
644
645 def commit(self, text, user, date):
646 cmd = ['commit', '-a', '-m', text]
647 if user:
648 cmd += ['--author', user]
649 if date:
650 # git's date parser silently ignores when seconds < 1e9
651 # convert to ISO8601
652 cmd += ['--date', util.datestr(date, '%Y-%m-%dT%H:%M:%S %1%2')]
653 self._gitcommand(cmd)
654 # make sure commit works otherwise HEAD might not exist under certain
655 # circumstances
656 return self._gitstate()
657
579 types = {
658 types = {
580 'hg': hgsubrepo,
659 'hg': hgsubrepo,
581 'svn': svnsubrepo,
660 'svn': svnsubrepo,
661 'git': gitsubrepo,
582 }
662 }
General Comments 0
You need to be logged in to leave comments. Login now