Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Bug 851270 - Don't clobber the source checkout. r=catlee

  • Loading branch information...
commit 10a1e46168773b48440f95ef0ade5bb8f636b078 1 parent c785d03
@gerva gerva authored
View
6 .gitignore
@@ -3,3 +3,9 @@ master_config.json
buildbot-configs
buildbotcustom
tools
+.coverage
+.tox
+coverage.xml
+lib/python/buildtools.egg-info/
+nosetests.xml
+
View
6 .hgignore
@@ -14,3 +14,9 @@ slavealloc.log
release-runner.ini
lib/python/slavealloc/www/icons
lib/python/slavealloc/www/js/bugzilla.js
+.coverage
+.tox
+coverage.xml
+lib/python/buildtools.egg-info/
+nosetests.xml
+
View
5 buildfarm/utils/hgtool.py
@@ -48,6 +48,8 @@
help="add a mirror to try cloning/pulling from before repo")
parser.add_option("--bundle", dest="bundles", action="append",
help="add a bundle to try downloading/unbundling from before doing a full clone")
+ parser.add_option("--purge", dest="auto_purge", action="store_true",
+ help="Purge the destination directory (if it exists).")
options, args = parser.parse_args()
@@ -85,6 +87,7 @@
shareBase=options.shared_dir,
clone_by_rev=options.clone_by_rev,
mirrors=options.mirrors,
- bundles=options.bundles)
+ bundles=options.bundles,
+ autoPurge=options.auto_purge)
print "Got revision %s" % got_revision
View
77 lib/python/mozilla_buildtools/test/test_util_hg.py
@@ -6,7 +6,7 @@
import util.hg as hg
from util.hg import clone, pull, update, hg_ver, mercurial, _make_absolute, \
- share, push, apply_and_push, HgUtilError, make_hg_url, get_branch, \
+ share, push, apply_and_push, HgUtilError, make_hg_url, get_branch, purge, \
get_branches, path, init, unbundle, adjust_paths, is_hg_cset, commit, tag
from util.commands import run_cmd, get_output
@@ -36,8 +36,8 @@ def getRevInfo(dest, rev):
def getTags(dest):
tags = []
- for tag in get_output(['hg', 'tags', '-R', dest]).splitlines():
- tags.append(tag.split()[0])
+ for t in get_output(['hg', 'tags', '-R', dest]).splitlines():
+ tags.append(t.split()[0])
return tags
@@ -298,6 +298,77 @@ def testPushWithRevision(self):
push(src=self.repodir, remote=self.wc, revision=self.revisions[-1])
self.assertEquals(getRevisions(self.wc), self.revisions[-2:])
+ def testPurgeUntrackedFile(self):
+ rev = clone(self.repodir, self.wc, update_dest=False)
+ self.assertEquals(rev, None)
+ fileToPurge=os.path.join(self.wc, 'fileToPurge')
+ with file(fileToPurge, 'a') as f:
+ f.write('purgeme')
+ purge(self.wc)
+ self.assertFalse(os.path.exists(fileToPurge))
+
+ def testPurgeUntrackedDirectory(self):
+ rev = clone(self.repodir, self.wc, update_dest=False)
+ self.assertEquals(rev, None)
+ directoryToPurge = os.path.join(self.wc, 'directoryToPurge')
+ os.makedirs(directoryToPurge)
+ purge(self.wc)
+ self.assertFalse(os.path.isdir(directoryToPurge))
+
+ def testPurgeTrackedFile(self):
+ rev = clone(self.repodir, self.wc, update_dest=False)
+ self.assertEquals(rev, None)
+ fileToModify = os.path.join(self.wc, 'purgetest.txt')
+ open(fileToModify, 'w').write('hello!')
+ run_cmd(['hg', 'add', 'purgetest.txt'], cwd=self.wc)
+ run_cmd(['hg', 'commit', '-m', 'adding changeset'], cwd=self.wc)
+ with open(fileToModify, 'w') as f:
+ f.write('just a test')
+ purge(self.wc)
+ content = open(fileToModify).read()
+ self.assertEqual(content, 'just a test')
+
+ def testPurgeUntrackedFile(self):
+ clone(self.repodir, self.wc)
+ fileToPurge=os.path.join(self.wc, 'fileToPurge')
+ with file(fileToPurge, 'a') as f:
+ f.write('purgeme')
+ purge(self.wc)
+ self.assertFalse(os.path.exists(fileToPurge))
+
+ def testPurgeUntrackedDirectory(self):
+ clone(self.repodir, self.wc)
+ directoryToPurge = os.path.join(self.wc, 'directoryTopPurge')
+ os.makedirs(directoryToPurge)
+ purge(directoryToPurge)
+ self.assertFalse(os.path.isdir(directoryToPurge))
+
+ def testPurgeVeryLongPath(self):
+ clone(self.repodir, self.wc)
+ # now create a very long path name
+ longPath = self.wc
+ for new_dir in xrange(1,64):
+ longPath = os.path.join(longPath, str(new_dir))
+ os.makedirs(longPath)
+ self.assertTrue(os.path.isdir(longPath))
+ purge(self.wc)
+ self.assertFalse(os.path.isdir(longPath))
+
+ def testPurgeAFreshClone(self):
+ clone(self.repodir, self.wc)
+ purge(self.wc)
+ self.assertTrue(os.path.exists(os.path.join(self.wc, 'hello.txt')))
+
+ def testPurgeTrackedFile(self):
+ clone(self.repodir, self.wc)
+ fileToModify = os.path.join(self.wc, 'hello.txt')
+ with open(fileToModify, 'w') as f:
+ f.write('hello!')
+ purge(self.wc)
+ with open(fileToModify, 'r') as f:
+ content = f.read()
+ self.assertEqual(content, 'hello!')
+
def testMercurial(self):
rev = mercurial(self.repodir, self.wc)
self.assertEquals(rev, self.revisions[0])
View
61 lib/python/util/commands.py
@@ -2,10 +2,16 @@
import subprocess
import os
import time
-
+import platform
import logging
log = logging.getLogger(__name__)
+try:
+ import win32file
+ import win32api
+ PYWIN32 = True
+except ImportError:
+ PYWIN32 = False
def log_cmd(cmd, **kwargs):
# cwd is special in that we always want it printed, even if it's not
@@ -161,6 +167,11 @@ def remove_path(path):
windows. Thanks to Bear at the OSAF for the code.
(Borrowed from buildbot.slave.commands)"""
log.debug("Removing %s", path)
+
+ if _is_windows():
+ _rmtree_windows(path)
+ return
+
if not os.path.exists(path):
# This handles broken links
if os.path.islink(path):
@@ -193,3 +204,51 @@ def remove_path(path):
os.chmod(full_name, 0700)
os.remove(full_name)
os.rmdir(path)
+
+
+# _is_windows and _rmtree_windows taken
+# from mozharness
+
+def _is_windows():
+ system = platform.system()
+ if system in ("Windows", "Microsoft"):
+ return True
+ if system.startswith("CYGWIN"):
+ return True
+ if os.name == 'nt':
+ return True
+
+def _rmtree_windows(path):
+ """ Windows-specific rmtree that handles path lengths longer than MAX_PATH.
+ Ported from clobberer.py.
+ """
+ log.info("Using _rmtree_windows ...")
+ assert _is_windows()
+ path = os.path.realpath(path)
+ full_path = '\\\\?\\' + path
+ if not os.path.exists(full_path):
+ return
+ if not PYWIN32:
+ if not os.path.isdir(path):
+ return run_cmd('del /F /Q "%s"' % path)
+ else:
+ return run_cmd('rmdir /S /Q "%s"' % path)
+ # Make sure directory is writable
+ win32file.SetFileAttributesW('\\\\?\\' + path, win32file.FILE_ATTRIBUTE_NORMAL)
+ # Since we call rmtree() with a file, sometimes
+ if not os.path.isdir('\\\\?\\' + path):
+ return win32file.DeleteFile('\\\\?\\' + path)
+
+ for ffrec in win32api.FindFiles('\\\\?\\' + path + '\\*.*'):
+ file_attr = ffrec[0]
+ name = ffrec[8]
+ if name == '.' or name == '..':
+ continue
+ full_name = os.path.join(path, name)
+
+ if file_attr & win32file.FILE_ATTRIBUTE_DIRECTORY:
+ _rmtree_windows(full_name)
+ else:
+ win32file.SetFileAttributesW('\\\\?\\' + full_name, win32file.FILE_ATTRIBUTE_NORMAL)
+ win32file.DeleteFile('\\\\?\\' + full_name)
+ win32file.RemoveDirectory('\\\\?\\' + path)
View
20 lib/python/util/hg.py
@@ -78,7 +78,7 @@ def is_hg_cset(rev):
"""Retruns True if passed revision represents a valid HG revision
(long or short(er) 40 bit hex)"""
try:
- _ = int(rev, 16)
+ int(rev, 16)
return True
except (TypeError, ValueError):
return False
@@ -99,6 +99,14 @@ def hg_ver():
log.debug("Running hg version %s", ver)
return ver
+def purge(dest):
+ """Purge the repository of all untracked and ignored files."""
+ try:
+ run_cmd(['hg', '--config', 'extensions.purge=', 'purge', '-a', '--all',
+ dest], cwd=os.path.normpath(os.path.join(dest, '..')))
+ except subprocess.CalledProcessError as e:
+ log.debug('purge failed: %s' %e)
+ raise
def update(dest, branch=None, revision=None):
"""Updates working copy `dest` to `branch` or `revision`. If neither is
@@ -187,7 +195,7 @@ def clone(repo, dest, branch=None, revision=None, update_dest=True,
# We need to make sure our paths are correct though
if os.path.exists(os.path.join(dest, '.hg')):
adjust_paths(dest, default=repo)
- return mercurial(repo, dest, branch, revision,
+ return mercurial(repo, dest, branch, revision, autoPurge=True,
update_dest=update_dest, clone_by_rev=clone_by_rev)
cmd = ['hg', 'clone']
@@ -317,7 +325,7 @@ def push(src, remote, push_new_branches=True, force=False, **kwargs):
def mercurial(repo, dest, branch=None, revision=None, update_dest=True,
shareBase=DefaultShareBase, allowUnsharedLocalClones=False,
- clone_by_rev=False, mirrors=None, bundles=None):
+ clone_by_rev=False, mirrors=None, bundles=None, autoPurge=False):
"""Makes sure that `dest` is has `revision` or `branch` checked out from
`repo`.
@@ -384,6 +392,8 @@ def mercurial(repo, dest, branch=None, revision=None, update_dest=True,
remove_path(dest)
elif not os.path.exists(os.path.join(dest, ".hg", "sharedpath")):
try:
+ if autoPurge:
+ purge(dest)
return pull(repo, dest, update_dest=update_dest, branch=branch,
revision=revision,
mirrors=mirrors)
@@ -425,8 +435,10 @@ def mercurial(repo, dest, branch=None, revision=None, update_dest=True,
log.info("Updating shared repo")
mercurial(repo, sharedRepo, branch=branch, revision=revision,
update_dest=False, shareBase=None, clone_by_rev=clone_by_rev,
- mirrors=mirrors, bundles=bundles)
+ mirrors=mirrors, bundles=bundles, autoPurge=False)
if os.path.exists(dest):
+ if autoPurge:
+ purge(dest)
return update(dest, branch=branch, revision=revision)
try:
View
25 tox.ini
@@ -0,0 +1,25 @@
+[tox]
+envlist = py27
+
+[testenv]
+deps =
+ nose==1.3.0
+ coverage==3.6
+ pep8==1.4.3
+ jinja2==2.6
+ mock==1.0.1
+ webob==1.2.3
+ gevent==0.13.8
+ IPy==0.81
+
+
+setenv =
+ PYTHONPATH = {toxinidir}/lib/python/vendor/poster-0.8.1:{toxinidir}/lib/python:{toxinidir}/lib/python/vendor:$PYTHONPATH
+
+commands =
+ coverage erase
+ coverage run --branch --source {toxinidir}/lib/python {envbindir}/nosetests --with-xunit {toxinidir}/lib/python
+
+[pep8]
+max-line-length = 159
+exclude = vendor,.tox,
Please sign in to comment.
Something went wrong with that request. Please try again.