PageRenderTime 43ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/hgext/purge.py

https://bitbucket.org/mirror/mercurial/
Python | 125 lines | 97 code | 4 blank | 24 comment | 3 complexity | 14ed660cd4b3e21a273a3a14e5287499 MD5 | raw file
Possible License(s): GPL-2.0
  1. # Copyright (C) 2006 - Marco Barisione <marco@barisione.org>
  2. #
  3. # This is a small extension for Mercurial (http://mercurial.selenic.com/)
  4. # that removes files not known to mercurial
  5. #
  6. # This program was inspired by the "cvspurge" script contained in CVS
  7. # utilities (http://www.red-bean.com/cvsutils/).
  8. #
  9. # For help on the usage of "hg purge" use:
  10. # hg help purge
  11. #
  12. # This program is free software; you can redistribute it and/or modify
  13. # it under the terms of the GNU General Public License as published by
  14. # the Free Software Foundation; either version 2 of the License, or
  15. # (at your option) any later version.
  16. #
  17. # This program is distributed in the hope that it will be useful,
  18. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. # GNU General Public License for more details.
  21. #
  22. # You should have received a copy of the GNU General Public License
  23. # along with this program; if not, see <http://www.gnu.org/licenses/>.
  24. '''command to delete untracked files from the working directory'''
  25. from mercurial import util, commands, cmdutil, scmutil
  26. from mercurial.i18n import _
  27. import os, stat
  28. cmdtable = {}
  29. command = cmdutil.command(cmdtable)
  30. testedwith = 'internal'
  31. @command('purge|clean',
  32. [('a', 'abort-on-err', None, _('abort if an error occurs')),
  33. ('', 'all', None, _('purge ignored files too')),
  34. ('', 'dirs', None, _('purge empty directories')),
  35. ('', 'files', None, _('purge files')),
  36. ('p', 'print', None, _('print filenames instead of deleting them')),
  37. ('0', 'print0', None, _('end filenames with NUL, for use with xargs'
  38. ' (implies -p/--print)')),
  39. ] + commands.walkopts,
  40. _('hg purge [OPTION]... [DIR]...'))
  41. def purge(ui, repo, *dirs, **opts):
  42. '''removes files not tracked by Mercurial
  43. Delete files not known to Mercurial. This is useful to test local
  44. and uncommitted changes in an otherwise-clean source tree.
  45. This means that purge will delete the following by default:
  46. - Unknown files: files marked with "?" by :hg:`status`
  47. - Empty directories: in fact Mercurial ignores directories unless
  48. they contain files under source control management
  49. But it will leave untouched:
  50. - Modified and unmodified tracked files
  51. - Ignored files (unless --all is specified)
  52. - New files added to the repository (with :hg:`add`)
  53. The --files and --dirs options can be used to direct purge to delete
  54. only files, only directories, or both. If neither option is given,
  55. both will be deleted.
  56. If directories are given on the command line, only files in these
  57. directories are considered.
  58. Be careful with purge, as you could irreversibly delete some files
  59. you forgot to add to the repository. If you only want to print the
  60. list of files that this program would delete, use the --print
  61. option.
  62. '''
  63. act = not opts['print']
  64. eol = '\n'
  65. if opts['print0']:
  66. eol = '\0'
  67. act = False # --print0 implies --print
  68. removefiles = opts['files']
  69. removedirs = opts['dirs']
  70. if not removefiles and not removedirs:
  71. removefiles = True
  72. removedirs = True
  73. def remove(remove_func, name):
  74. if act:
  75. try:
  76. remove_func(repo.wjoin(name))
  77. except OSError:
  78. m = _('%s cannot be removed') % name
  79. if opts['abort_on_err']:
  80. raise util.Abort(m)
  81. ui.warn(_('warning: %s\n') % m)
  82. else:
  83. ui.write('%s%s' % (name, eol))
  84. def removefile(path):
  85. try:
  86. os.remove(path)
  87. except OSError:
  88. # read-only files cannot be unlinked under Windows
  89. s = os.stat(path)
  90. if (s.st_mode & stat.S_IWRITE) != 0:
  91. raise
  92. os.chmod(path, stat.S_IMODE(s.st_mode) | stat.S_IWRITE)
  93. os.remove(path)
  94. directories = []
  95. match = scmutil.match(repo[None], dirs, opts)
  96. match.explicitdir = match.traversedir = directories.append
  97. status = repo.status(match=match, ignored=opts['all'], unknown=True)
  98. if removefiles:
  99. for f in sorted(status[4] + status[5]):
  100. if act:
  101. ui.note(_('removing file %s\n') % f)
  102. remove(removefile, f)
  103. if removedirs:
  104. for f in sorted(directories, reverse=True):
  105. if match(f) and not os.listdir(repo.wjoin(f)):
  106. if act:
  107. ui.note(_('removing directory %s\n') % f)
  108. remove(os.rmdir, f)