mercurial/subrepo.py
changeset 12995 d90fc91c8377
parent 12994 845c602b8635
child 12996 3a42651b0a62
equal deleted inserted replaced
12994:845c602b8635 12995:d90fc91c8377
   632 
   632 
   633     def _githavelocally(self, revision):
   633     def _githavelocally(self, revision):
   634         out, code = self._gitdir(['cat-file', '-e', revision])
   634         out, code = self._gitdir(['cat-file', '-e', revision])
   635         return code == 0
   635         return code == 0
   636 
   636 
       
   637     def _gitbranchmap(self):
       
   638         'returns the current branch and a map from git revision to branch[es]'
       
   639         bm = {}
       
   640         redirects = {}
       
   641         current = None
       
   642         out = self._gitcommand(['branch', '-a', '--no-color',
       
   643                                 '--verbose', '--abbrev=40'])
       
   644         for line in out.split('\n'):
       
   645             if not line:
       
   646                 continue
       
   647             if line[2:].startswith('(no branch)'):
       
   648                 continue
       
   649             branch, revision = line[2:].split()[:2]
       
   650             if revision == '->':
       
   651                 continue # ignore remote/HEAD redirects
       
   652             if line[0] == '*':
       
   653                 current = branch
       
   654             bm.setdefault(revision, []).append(branch)
       
   655         return current, bm
       
   656 
   637     def _fetch(self, source, revision):
   657     def _fetch(self, source, revision):
   638         if not os.path.exists('%s/.git' % self._path):
   658         if not os.path.exists('%s/.git' % self._path):
   639             self._ui.status(_('cloning subrepo %s\n') % self._relpath)
   659             self._ui.status(_('cloning subrepo %s\n') % self._relpath)
   640             self._gitnodir(['clone', source, self._path])
   660             self._gitnodir(['clone', source, self._path])
   641         if self._githavelocally(revision):
   661         if self._githavelocally(revision):
   656         return bool(changed.strip())
   676         return bool(changed.strip())
   657 
   677 
   658     def get(self, state):
   678     def get(self, state):
   659         source, revision, kind = state
   679         source, revision, kind = state
   660         self._fetch(source, revision)
   680         self._fetch(source, revision)
   661         if self._gitstate() != revision:
   681         if self._gitstate() == revision:
       
   682             return
       
   683         current, bm = self._gitbranchmap()
       
   684         if revision not in bm:
       
   685             # no branch to checkout, check it out with no branch
   662             self._ui.warn(_('checking out detached HEAD in subrepo %s\n') %
   686             self._ui.warn(_('checking out detached HEAD in subrepo %s\n') %
   663                           self._relpath)
   687                           self._relpath)
   664             self._ui.warn(_('check out a git branch if you intend '
   688             self._ui.warn(_('check out a git branch if you intend '
   665                             'to make changes\n'))
   689                             'to make changes\n'))
   666             self._gitcommand(['checkout', '-q', revision])
   690             self._gitcommand(['checkout', '-q', revision])
       
   691             return
       
   692         branches = bm[revision]
       
   693         firstlocalbranch = None
       
   694         for b in branches:
       
   695             if b == 'master':
       
   696                 # master trumps all other branches
       
   697                 self._gitcommand(['checkout', 'master'])
       
   698                 return
       
   699             if not firstlocalbranch and not b.startswith('remotes/'):
       
   700                 firstlocalbranch = b
       
   701         if firstlocalbranch:
       
   702             self._gitcommand(['checkout', firstlocalbranch])
       
   703         else:
       
   704             remote = branches[0]
       
   705             local = remote.split('/')[-1]
       
   706             self._gitcommand(['checkout', '-b', local, remote])
   667 
   707 
   668     def commit(self, text, user, date):
   708     def commit(self, text, user, date):
   669         cmd = ['commit', '-a', '-m', text]
   709         cmd = ['commit', '-a', '-m', text]
   670         if user:
   710         if user:
   671             cmd += ['--author', user]
   711             cmd += ['--author', user]
   690 
   730 
   691     def push(self, force):
   731     def push(self, force):
   692         cmd = ['push']
   732         cmd = ['push']
   693         if force:
   733         if force:
   694             cmd.append('--force')
   734             cmd.append('--force')
   695         # as subrepos have no notion of "where to push to" we
   735         # push the currently checked out branch
   696         # assume origin master. This is git's default
   736         current, bm = self._gitbranchmap()
   697         self._gitcommand(cmd + ['origin', 'master', '-q'])
   737         if current:
   698         return True
   738             self._gitcommand(cmd + ['origin', current, '-q'])
       
   739             return True
       
   740         else:
       
   741             self._ui.warn(_('no branch checked out in subrepo %s\n'
       
   742                             'nothing to push') % self._relpath)
       
   743             return False
   699 
   744 
   700 types = {
   745 types = {
   701     'hg': hgsubrepo,
   746     'hg': hgsubrepo,
   702     'svn': svnsubrepo,
   747     'svn': svnsubrepo,
   703     'git': gitsubrepo,
   748     'git': gitsubrepo,