hgext/purge.py
changeset 5517 98d5f9b95699
parent 5147 c80af96943aa
child 6212 e75aab656f46
equal deleted inserted replaced
5516:f252ba975925 5517:98d5f9b95699
    47             except OSError, e:
    47             except OSError, e:
    48                 error(_('%s cannot be removed') % name)
    48                 error(_('%s cannot be removed') % name)
    49         else:
    49         else:
    50             ui.write('%s%s' % (name, eol))
    50             ui.write('%s%s' % (name, eol))
    51 
    51 
       
    52     if not force:
       
    53         _check_fs(ui, repo)
       
    54 
    52     directories = []
    55     directories = []
    53     files = []
    56     files = []
    54     missing = []
    57     missing = []
    55     roots, match, anypats = util.cmdmatcher(repo.root, repo.getcwd(), dirs,
    58     roots, match, anypats = util.cmdmatcher(repo.root, repo.getcwd(), dirs,
    56                                             include, exclude)
    59                                             include, exclude)
    61         elif src == 'm':
    64         elif src == 'm':
    62             missing.append(f)
    65             missing.append(f)
    63         elif src == 'f' and f not in repo.dirstate:
    66         elif src == 'f' and f not in repo.dirstate:
    64             files.append(f)
    67             files.append(f)
    65 
    68 
    66     _check_missing(ui, repo, missing, force)
       
    67 
       
    68     directories.sort()
    69     directories.sort()
    69 
    70 
    70     for f in files:
    71     for f in files:
    71         if f not in repo.dirstate:
    72         if f not in repo.dirstate:
    72             ui.note(_('Removing file %s\n') % f)
    73             ui.note(_('Removing file %s\n') % f)
    75     for f in directories[::-1]:
    76     for f in directories[::-1]:
    76         if match(f) and not os.listdir(repo.wjoin(f)):
    77         if match(f) and not os.listdir(repo.wjoin(f)):
    77             ui.note(_('Removing directory %s\n') % f)
    78             ui.note(_('Removing directory %s\n') % f)
    78             remove(os.rmdir, f)
    79             remove(os.rmdir, f)
    79 
    80 
    80 def _check_missing(ui, repo, missing, force=False):
    81 def _check_fs(ui, repo):
    81     """Abort if there is the chance of having problems with name-mangling fs
    82     """Abort if there is the chance of having problems with name-mangling fs
    82 
    83 
    83     In a name mangling filesystem (e.g. a case insensitive one)
    84     In a name mangling filesystem (e.g. a case insensitive one)
    84     dirstate.walk() can yield filenames different from the ones
    85     dirstate.walk() can yield filenames different from the ones
    85     stored in the dirstate. This already confuses the status and
    86     stored in the dirstate. This already confuses the status and
    86     add commands, but with purge this may cause data loss.
    87     add commands, but with purge this may cause data loss.
    87 
    88 
    88     To prevent this, _check_missing will abort if there are missing
    89     To prevent this, this function will abort if there are uncommitted
    89     files. The force option will let the user skip the check if he
    90     changes.
    90     knows it is safe.
    91     """
    91 
    92 
    92     Even with the force option this function will check if any of the
    93     # We can't use (files, match) to do a partial walk here - we wouldn't
    93     missing files is still available in the working dir: if so there
    94     # notice a modified README file if the user ran "hg purge readme"
    94     may be some problem with the underlying filesystem, so it
    95     modified, added, removed, deleted = repo.status()[:4]
    95     aborts unconditionally."""
    96     if modified or added or removed or deleted:
    96 
    97         if not util.checkfolding(repo.path) and not ui.quiet:
    97     found = [f for f in missing if util.lexists(repo.wjoin(f))]
    98             ui.warn(_("Purging on name mangling filesystems is not "
    98 
    99                       "fully supported.\n"))
    99     if found:
   100         raise util.Abort(_("outstanding uncommitted changes"))
   100         if not ui.quiet:
       
   101             ui.warn(_("The following tracked files weren't listed by the "
       
   102                       "filesystem, but could still be found:\n"))
       
   103             for f in found:
       
   104                 ui.warn("%s\n" % f)
       
   105             if util.checkfolding(repo.path):
       
   106                 ui.warn(_("This is probably due to a case-insensitive "
       
   107                           "filesystem\n"))
       
   108         raise util.Abort(_("purging on name mangling filesystems is not "
       
   109                            "yet fully supported"))
       
   110 
       
   111     if missing and not force:
       
   112         raise util.Abort(_("there are missing files in the working dir and "
       
   113                            "purge still has problems with them due to name "
       
   114                            "mangling filesystems. "
       
   115                            "Use --force if you know what you are doing"))
       
   116 
   101 
   117 
   102 
   118 def purge(ui, repo, *dirs, **opts):
   103 def purge(ui, repo, *dirs, **opts):
   119     '''removes files not tracked by mercurial
   104     '''removes files not tracked by mercurial
   120 
   105 
   156 cmdtable = {
   141 cmdtable = {
   157     'purge|clean':
   142     'purge|clean':
   158         (purge,
   143         (purge,
   159          [('a', 'abort-on-err', None, _('abort if an error occurs')),
   144          [('a', 'abort-on-err', None, _('abort if an error occurs')),
   160           ('',  'all', None, _('purge ignored files too')),
   145           ('',  'all', None, _('purge ignored files too')),
   161           ('f', 'force', None, _('purge even when missing files are detected')),
   146           ('f', 'force', None, _('purge even when there are uncommitted changes')),
   162           ('p', 'print', None, _('print the file names instead of deleting them')),
   147           ('p', 'print', None, _('print the file names instead of deleting them')),
   163           ('0', 'print0', None, _('end filenames with NUL, for use with xargs'
   148           ('0', 'print0', None, _('end filenames with NUL, for use with xargs'
   164                                   ' (implies -p)')),
   149                                   ' (implies -p)')),
   165          ] + commands.walkopts,
   150          ] + commands.walkopts,
   166          _('hg purge [OPTION]... [DIR]...'))
   151          _('hg purge [OPTION]... [DIR]...'))