mercurial/commands.py
changeset 2803 987c31e2a08c
parent 2802 fdc232d8a193
parent 2794 bd8a9a94139f
child 2820 0bf22c109cc3
equal deleted inserted replaced
2802:fdc232d8a193 2803:987c31e2a08c
    38     cwd = repo.getcwd()
    38     cwd = repo.getcwd()
    39     if cwd:
    39     if cwd:
    40         return [util.normpath(os.path.join(cwd, x)) for x in args]
    40         return [util.normpath(os.path.join(cwd, x)) for x in args]
    41     return args
    41     return args
    42 
    42 
    43 def logmessage(**opts):
    43 def logmessage(opts):
    44     """ get the log message according to -m and -l option """
    44     """ get the log message according to -m and -l option """
    45     message = opts['message']
    45     message = opts['message']
    46     logfile = opts['logfile']
    46     logfile = opts['logfile']
    47 
    47 
    48     if message and logfile:
    48     if message and logfile:
   123                 if windowsize < sizelimit:
   123                 if windowsize < sizelimit:
   124                     windowsize *= 2
   124                     windowsize *= 2
   125 
   125 
   126 
   126 
   127     files, matchfn, anypats = matchpats(repo, pats, opts)
   127     files, matchfn, anypats = matchpats(repo, pats, opts)
   128     follow = opts.get('follow')
   128     follow = opts.get('follow') or opts.get('follow_first')
   129 
   129 
   130     if repo.changelog.count() == 0:
   130     if repo.changelog.count() == 0:
   131         return [], False, matchfn
   131         return [], False, matchfn
   132 
   132 
   133     revs = map(int, revrange(ui, repo, opts['rev'] or ['tip:0']))
   133     if follow:
       
   134         p = repo.dirstate.parents()[0]
       
   135         if p == nullid:
       
   136             ui.warn(_('No working directory revision; defaulting to tip\n'))
       
   137             start = 'tip'
       
   138         else:
       
   139             start = repo.changelog.rev(p)
       
   140         defrange = '%s:0' % start
       
   141     else:
       
   142         defrange = 'tip:0'
       
   143     revs = map(int, revrange(ui, repo, opts['rev'] or [defrange]))
   134     wanted = {}
   144     wanted = {}
   135     slowpath = anypats
   145     slowpath = anypats
   136     fncache = {}
   146     fncache = {}
   137 
   147 
   138     chcache = {}
   148     chcache = {}
   204             if matches:
   214             if matches:
   205                 fncache[rev] = matches
   215                 fncache[rev] = matches
   206                 wanted[rev] = 1
   216                 wanted[rev] = 1
   207 
   217 
   208     def iterate():
   218     def iterate():
       
   219         class followfilter:
       
   220             def __init__(self, onlyfirst=False):
       
   221                 self.startrev = -1
       
   222                 self.roots = []
       
   223                 self.onlyfirst = onlyfirst
       
   224 
       
   225             def match(self, rev):
       
   226                 def realparents(rev):
       
   227                     if self.onlyfirst:
       
   228                         return repo.changelog.parentrevs(rev)[0:1]
       
   229                     else:
       
   230                         return filter(lambda x: x != -1, repo.changelog.parentrevs(rev))
       
   231 
       
   232                 if self.startrev == -1:
       
   233                     self.startrev = rev
       
   234                     return True
       
   235 
       
   236                 if rev > self.startrev:
       
   237                     # forward: all descendants
       
   238                     if not self.roots:
       
   239                         self.roots.append(self.startrev)
       
   240                     for parent in realparents(rev):
       
   241                         if parent in self.roots:
       
   242                             self.roots.append(rev)
       
   243                             return True
       
   244                 else:
       
   245                     # backwards: all parents
       
   246                     if not self.roots:
       
   247                         self.roots.extend(realparents(self.startrev))
       
   248                     if rev in self.roots:
       
   249                         self.roots.remove(rev)
       
   250                         self.roots.extend(realparents(rev))
       
   251                         return True
       
   252 
       
   253                 return False
       
   254 
       
   255         if follow and not files:
       
   256             ff = followfilter(onlyfirst=opts.get('follow_first'))
       
   257             def want(rev):
       
   258                 if rev not in wanted:
       
   259                     return False
       
   260                 return ff.match(rev)
       
   261         else:
       
   262             def want(rev):
       
   263                 return rev in wanted
       
   264 
   209         for i, window in increasing_windows(0, len(revs)):
   265         for i, window in increasing_windows(0, len(revs)):
   210             yield 'window', revs[0] < revs[-1], revs[-1]
   266             yield 'window', revs[0] < revs[-1], revs[-1]
   211             nrevs = [rev for rev in revs[i:i+window]
   267             nrevs = [rev for rev in revs[i:i+window] if want(rev)]
   212                      if rev in wanted]
       
   213             srevs = list(nrevs)
   268             srevs = list(nrevs)
   214             srevs.sort()
   269             srevs.sort()
   215             for rev in srevs:
   270             for rev in srevs:
   216                 fns = fncache.get(rev) or filter(matchfn, getchange(rev)[3])
   271                 fns = fncache.get(rev) or filter(matchfn, getchange(rev)[3])
   217                 yield 'add', rev, fns
   272                 yield 'add', rev, fns
  1039     will be committed.
  1094     will be committed.
  1040 
  1095 
  1041     If no commit message is specified, the editor configured in your hgrc
  1096     If no commit message is specified, the editor configured in your hgrc
  1042     or in the EDITOR environment variable is started to enter a message.
  1097     or in the EDITOR environment variable is started to enter a message.
  1043     """
  1098     """
  1044     message = logmessage(**opts)
  1099     message = logmessage(opts)
  1045 
  1100 
  1046     if opts['addremove']:
  1101     if opts['addremove']:
  1047         addremove_lock(ui, repo, pats, opts)
  1102         addremove_lock(ui, repo, pats, opts)
  1048     fns, match, anypats = matchpats(repo, pats, opts)
  1103     fns, match, anypats = matchpats(repo, pats, opts)
  1049     if pats:
  1104     if pats:
  1970 
  2025 
  1971     Print the revision history of the specified files or the entire
  2026     Print the revision history of the specified files or the entire
  1972     project.
  2027     project.
  1973 
  2028 
  1974     File history is shown without following rename or copy history of
  2029     File history is shown without following rename or copy history of
  1975     files.  Use -f/--follow to follow history across renames and
  2030     files.  Use -f/--follow with a file name to follow history across
  1976     copies.
  2031     renames and copies. --follow without a file name will only show
       
  2032     ancestors or descendants of the starting revision. --follow-first
       
  2033     only follows the first parent of merge revisions.
       
  2034 
       
  2035     If no revision range is specified, the default is tip:0 unless
       
  2036     --follow is set, in which case the working directory parent is
       
  2037     used as the starting revision.
  1977 
  2038 
  1978     By default this command outputs: changeset id and hash, tags,
  2039     By default this command outputs: changeset id and hash, tags,
  1979     non-trivial parents, user, date and time, and a summary for each
  2040     non-trivial parents, user, date and time, and a summary for each
  1980     commit. When the -v/--verbose switch is used, the list of changed
  2041     commit. When the -v/--verbose switch is used, the list of changed
  1981     files and full commit message is shown.
  2042     files and full commit message is shown.
  2726     they are stored as a file named ".hgtags" which is managed
  2787     they are stored as a file named ".hgtags" which is managed
  2727     similarly to other project files and can be hand-edited if
  2788     similarly to other project files and can be hand-edited if
  2728     necessary.  The file '.hg/localtags' is used for local tags (not
  2789     necessary.  The file '.hg/localtags' is used for local tags (not
  2729     shared among repositories).
  2790     shared among repositories).
  2730     """
  2791     """
  2731     if name == "tip":
  2792     if name in ['tip', '.']:
  2732         raise util.Abort(_("the name 'tip' is reserved"))
  2793         raise util.Abort(_("the name '%s' is reserved") % name)
  2733     if rev_ is not None:
  2794     if rev_ is not None:
  2734         ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, "
  2795         ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, "
  2735                   "please use 'hg tag [-r REV] NAME' instead\n"))
  2796                   "please use 'hg tag [-r REV] NAME' instead\n"))
  2736         if opts['rev']:
  2797         if opts['rev']:
  2737             raise util.Abort(_("use only one form to specify the revision"))
  2798             raise util.Abort(_("use only one form to specify the revision"))
  3085          _('hg locate [OPTION]... [PATTERN]...')),
  3146          _('hg locate [OPTION]... [PATTERN]...')),
  3086     "^log|history":
  3147     "^log|history":
  3087         (log,
  3148         (log,
  3088          [('b', 'branches', None, _('show branches')),
  3149          [('b', 'branches', None, _('show branches')),
  3089           ('f', 'follow', None,
  3150           ('f', 'follow', None,
  3090            _('follow file history across copies and renames')),
  3151            _('follow changeset history, or file history across copies and renames')),
       
  3152           ('', 'follow-first', None,
       
  3153            _('only follow the first parent of merge changesets')),
  3091           ('k', 'keyword', [], _('search for a keyword')),
  3154           ('k', 'keyword', [], _('search for a keyword')),
  3092           ('l', 'limit', '', _('limit number of changes displayed')),
  3155           ('l', 'limit', '', _('limit number of changes displayed')),
  3093           ('r', 'rev', [], _('show the specified revision or range')),
  3156           ('r', 'rev', [], _('show the specified revision or range')),
  3094           ('M', 'no-merges', None, _('do not show merges')),
  3157           ('M', 'no-merges', None, _('do not show merges')),
  3095           ('', 'style', '', _('display using template map file')),
  3158           ('', 'style', '', _('display using template map file')),