1. Markus Zapke-Gründemann
  2. hg-importfs

Commits

Markus Zapke-Gründemann  committed bbeef05

HGSUP-162, HGSUP-163: Added new options exclude and ignore-copy-errors.

  • Participants
  • Parent commits 335ff93
  • Branches default

Comments (0)

Files changed (3)

File .hgignore

View file
 *.swp
 run-tests.py
 dist
+pylintrc
 MANIFEST

File importfs.py

View file
 
 __version__ = '0.9.0'
 
+
 def get_repo(ui, path):
     """Initialize or create a repository."""
     try:
         ui.status(_('created repository %s\n' % repo.root))
     return repo
 
+
 def update_repo(ui, repo, rev, branch=None):
     """Update the repository.
 
     else:
         commands.update(ui, repo)
 
+
 def onerror(func, path, exc_info=tuple()):
     """Error handler for shutil.rmtree and methods of the os package.
 
     else:
         raise
 
+
 def purge_repo(repo):
     """Empty the repository except the metadata."""
     for node in os.listdir(repo.root):
             except WindowsError:
                 onerror(os.remove, path)
 
+
+def copyfiles(src, dst, exclude=None, ignore_errors=False):
+    """Copy recursively from src to dst directory.
+
+    If src is a file copy only the file.
+
+    If src is a directory copy recursively the entire directory tree. The
+    destination directory, named by dst, must not already exist; it will be
+    created as well as missing parent directories.
+
+    All files and directories matching the exclude pattern will be ignored. The
+    pattern '*.pyc tmp*' will copy everything except .pyc files and files or
+    directories whose name starts with tmp.
+
+    If ignore_errors is True all errors will be returned as a list of warnings.
+    """
+    warnings = []
+    try:
+        if exclude:
+            ignore = shutil.ignore_patterns(*exclude.split())
+            if len(ignore(src, os.path.split(src))):
+                # Terminate immediately if the src path matches the exclude
+                # pattern.
+                return warnings
+        else:
+            ignore = None
+        if os.path.isdir(src):
+            shutil.copytree(src, dst, ignore=ignore)
+        else:
+            shutil.copy(src, dst)
+    except shutil.Error, err:
+        if not ignore_errors:
+            raise
+        warnings.append(err)
+    return warnings
+
+
 def importfs(ui, repo, source, *pats, **opts):
     """Import a set of files from a file-system into a repository.
 
         for node in os.listdir(sourcepath):
             src = os.path.join(sourcepath, node)
             dst = os.path.join(repo.root, node)
-            util.copyfiles(src, dst, False)
+            warnings = copyfiles(src, dst, opts.get('exclude'),
+                opts.get('ignore_copy_errors'))
+            if len(warnings):
+                # Print warnings.
+                for warning in warnings:
+                    ui.warn('Warning: Failed to copy %s to %s (%s).\n' %
+                        warning.args[0][0])
     commands.addremove(ui, repo, similarity=opts.get('similarity'))
     message = opts.get('message') or 'importfs commit.'
     commands.commit(ui, repo, message=message)
     if tag:
         commands.tag(ui, repo, tag)
 
+
 cmdtable = {'importfs':
     (importfs,
     [('r', 'rev', '', _('The revision to use as the immediate predecessor of '
     ('m', 'message', '', _('The commit message to be used. If omitted the '
         'tag string is used.'), _('TEXT')),
     ('t', 'tag', '', _('The tag for the resulting revision. If omitted the '
-        'revision is not tagged.'), _('NAME'))],
+        'revision is not tagged.'), _('NAME')),
+    ('', 'exclude', '', _('Exclude all files matching the given pattern.'),
+        _('PATTERN')),
+    ('', 'ignore-copy-errors', None, _('Turn all errors during the file copy '
+        'operation into warnings.'))],
     '[OPTION]... REPO SOURCE...')
 }
 commands.norepo += ' importfs'

File test-importfs-copytree.t

View file
+Load the extension:
+
+  $ echo "[extensions]" >> $HGRCPATH
+  $ echo "importfs = $TESTDIR/importfs.py" >> $HGRCPATH
+
+Create a simple filesystem structure for import:
+
+  $ mkdir d1
+  $ echo "c1" > d1/f1
+  $ echo "c2" > d1/f2
+  $ mkdir d1/d2
+  $ echo "c3" > d1/d2/f3
+  $ mkdir d1/d3
+  $ echo "c4" > d1/d3/f4
+  $ echo "c5" > d1/d3/f5
+  $ mkdir d1/d4
+  $ echo "c6" > d1/d4/f6
+  $ echo "c7" > d1/d4/f7
+
+Perform an import ignoring the file f2 and the d3 directory:
+
+  $ hg importfs r1 d1 --exclude "f2 d3"
+  created repository $TESTTMP/r1
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  adding d2/f3
+  adding d4/f6
+  adding d4/f7
+  adding f1
+
+Perform an import with a wildcard exclude expression:
+
+  $ hg importfs r2 d1 --exclude "*3"
+  created repository $TESTTMP/r2
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  adding d4/f6
+  adding d4/f7
+  adding f1
+  adding f2
+
+Perform an import with an unreadable file with suppressed errors:
+
+  $ chmod u-r d1/d2/f3
+  $ hg importfs r3 d1 --ignore-copy-errors
+  created repository $TESTTMP/r3
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  Warning: Failed to copy d1/d2/f3 to $TESTTMP/r3/d2/f3 ([Errno 13] Permission denied: 'd1/d2/f3').
+  adding d3/f4
+  adding d3/f5
+  adding d4/f6
+  adding d4/f7
+  adding f1
+  adding f2
+