3 # Copyright 2009-2010 Matt Mackall <mpm@selenic.com> |
3 # Copyright 2009-2010 Matt Mackall <mpm@selenic.com> |
4 # |
4 # |
5 # This software may be used and distributed according to the terms of the |
5 # This software may be used and distributed according to the terms of the |
6 # GNU General Public License version 2 or any later version. |
6 # GNU General Public License version 2 or any later version. |
7 |
7 |
8 import errno, os, re, xml.dom.minidom, shutil, subprocess, urlparse, posixpath |
8 import errno, os, re, xml.dom.minidom, shutil, urlparse, posixpath |
|
9 import stat, subprocess |
9 from i18n import _ |
10 from i18n import _ |
10 import config, util, node, error, cmdutil |
11 import config, util, node, error, cmdutil |
11 hg = None |
12 hg = None |
12 |
13 |
13 nullstate = ('', '', 'empty') |
14 nullstate = ('', '', 'empty') |
478 cmd = [util.shellquote(arg) for arg in cmd] |
479 cmd = [util.shellquote(arg) for arg in cmd] |
479 cmd = util.quotecommand(' '.join(cmd)) |
480 cmd = util.quotecommand(' '.join(cmd)) |
480 env = dict(os.environ) |
481 env = dict(os.environ) |
481 # Avoid localized output, preserve current locale for everything else. |
482 # Avoid localized output, preserve current locale for everything else. |
482 env['LC_MESSAGES'] = 'C' |
483 env['LC_MESSAGES'] = 'C' |
483 write, read, err = util.popen3(cmd, env=env, newlines=True) |
484 p = subprocess.Popen(cmd, shell=True, bufsize=-1, |
484 retdata = read.read() |
485 close_fds=util.closefds, |
485 err = err.read().strip() |
486 stdout=subprocess.PIPE, stderr=subprocess.PIPE, |
486 if err: |
487 universal_newlines=True, env=env) |
487 raise util.Abort(err) |
488 stdout, stderr = p.communicate() |
488 return retdata |
489 stderr = stderr.strip() |
|
490 if stderr: |
|
491 raise util.Abort(stderr) |
|
492 return stdout |
489 |
493 |
490 def _wcrev(self): |
494 def _wcrev(self): |
491 output = self._svncommand(['info', '--xml']) |
495 output = self._svncommand(['info', '--xml']) |
492 doc = xml.dom.minidom.parseString(output) |
496 doc = xml.dom.minidom.parseString(output) |
493 entries = doc.getElementsByTagName('entry') |
497 entries = doc.getElementsByTagName('entry') |
547 if self.dirty(): |
551 if self.dirty(): |
548 self._ui.warn(_('not removing repo %s because ' |
552 self._ui.warn(_('not removing repo %s because ' |
549 'it has changes.\n' % self._path)) |
553 'it has changes.\n' % self._path)) |
550 return |
554 return |
551 self._ui.note(_('removing subrepo %s\n') % self._path) |
555 self._ui.note(_('removing subrepo %s\n') % self._path) |
552 shutil.rmtree(self._ctx._repo.wjoin(self._path)) |
556 |
|
557 def onerror(function, path, excinfo): |
|
558 if function is not os.remove: |
|
559 raise |
|
560 # read-only files cannot be unlinked under Windows |
|
561 s = os.stat(path) |
|
562 if (s.st_mode & stat.S_IWRITE) != 0: |
|
563 raise |
|
564 os.chmod(path, stat.S_IMODE(s.st_mode) | stat.S_IWRITE) |
|
565 os.remove(path) |
|
566 |
|
567 path = self._ctx._repo.wjoin(self._path) |
|
568 shutil.rmtree(path, onerror=onerror) |
|
569 try: |
|
570 os.removedirs(os.path.dirname(path)) |
|
571 except OSError: |
|
572 pass |
553 |
573 |
554 def get(self, state): |
574 def get(self, state): |
555 status = self._svncommand(['checkout', state[0], '--revision', state[1]]) |
575 status = self._svncommand(['checkout', state[0], '--revision', state[1]]) |
556 if not re.search('Checked out revision [0-9]+.', status): |
576 if not re.search('Checked out revision [0-9]+.', status): |
557 raise util.Abort(status.splitlines()[-1]) |
577 raise util.Abort(status.splitlines()[-1]) |