* [RFC PATCH] Add new git-cp command, transposed from stgit.
@ 2007-05-17 20:49 Yann Dirson
2007-05-18 7:57 ` Karl Hasselström
0 siblings, 1 reply; 2+ messages in thread
From: Yann Dirson @ 2007-05-17 20:49 UTC (permalink / raw)
To: git
This git-cp command is recursive when acting on directories, but only
copies files under git control.
---
Addition of this command would be along the lines of "move into git
things from stgit that are not specific to stgit".
A known annoying limitation of this version (very quickly adapted) is
that quoted files in the "git ls-files" output trigger the assert()
clause. I'd use "-z", but it looks like noone wrote a zero-separated
file reader for python (how that makes me regret perl ;).
I can surely write one, but do we want this to be in python after all ?
At least in perl it would be easy to fix this issue, but do we even
accept perl scripts for such features ? OTOH, I'm not sure it is
worth rewriting in C...
git-cp.py | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 141 insertions(+), 0 deletions(-)
diff --git a/git-cp.py b/git-cp.py
new file mode 100755
index 0000000..8df2e73
--- /dev/null
+++ b/git-cp.py
@@ -0,0 +1,141 @@
+#!/usr/bin/python
+#
+# This tool is copyright (c) 2007, Yann Dirson.
+# Parts copyright (c) 2005 Catalin Marinas.
+# It is released under the Gnu Public License, version 2.
+#
+
+import os, sys, getopt, popen2, re
+from shutil import copyfile
+
+def usage():
+ print "USAGE: git-cp <source>... <destination>"
+ sys.exit(1)
+
+## functions copied from stgit.git 0.12
+
+def _output_lines(cmd):
+ p=popen2.Popen3(cmd, True)
+ lines = p.fromchild.readlines()
+ if p.wait():
+ raise Exception, '%s failed (%s)' % (str(cmd),
+ p.childerr.read().strip())
+ return lines
+
+def __run(cmd, args=None):
+ """__run: runs cmd using spawnvp.
+
+ Runs cmd using spawnvp. The shell is avoided so it won't mess up
+ our arguments. If args is very large, the command is run multiple
+ times; args is split xargs style: cmd is passed on each
+ invocation. Unlike xargs, returns immediately if any non-zero
+ return code is received.
+ """
+
+ args_l=cmd.split()
+ if args is None:
+ args = []
+ for i in range(0, len(args)+1, 100):
+ r=os.spawnvp(os.P_WAIT, args_l[0], args_l + args[i:min(i+100, len(args))])
+ if r:
+ return r
+ return 0
+
+# functions adapted from stgit.git 0.12
+
+def addfiles(names):
+ """Add the files
+ """
+ # check the file list
+ for i in names:
+ if not os.path.exists(i):
+ raise Exception, 'Unknown file: %s' % i
+ if not os.path.isfile(i):
+ raise Exception, '%s is not a plain file' % i
+
+ if names:
+ if __run('git-update-index --add --', names):
+ raise Exception, 'Unable to add file'
+
+# core "git-cp" implementation
+
+def __copy_singlefile(source, target, target2=''):
+ """Copy file or dir named 'source' to name target+target2"""
+
+ # "source" (file or dir) must match one or more git-controlled file
+ realfiles = _output_lines(['git-ls-files', source])
+ if len(realfiles) == 0:
+ raise Exception, '"%s" matches no git-controled files' % source
+
+ if os.path.isdir(source):
+ # physically copy the files, and record them to add them in one run
+ newfiles = []
+ re_string='^'+source+'/(.*)$'
+ prefix_regexp = re.compile(re_string)
+ for f in [f.strip() for f in realfiles]:
+ m = prefix_regexp.match(f)
+ if not m:
+ print '"%s" does not match "%s"' % (f, re_string)
+ assert(m)
+ newname = target+target2+'/'+m.group(1)
+ if not os.path.exists(os.path.dirname(newname)):
+ os.makedirs(os.path.dirname(newname))
+ copyfile(f, newname)
+ newfiles.append(newname)
+
+ addfiles(newfiles)
+ else: # files, symlinks, ...
+ newname = target+target2
+ copyfile(source, newname)
+ addfiles([newname])
+
+
+def copy(filespecs, target):
+ if os.path.isdir(target):
+ # target is a directory: copy each entry on the command line,
+ # with the same name, into the target
+ target = target.rstrip('/')
+
+ # first, check that none of the children of the target
+ # matching the command line aleady exist
+ for filespec in filespecs:
+ entry = target+ '/' + os.path.basename(filespec.rstrip('/'))
+ if os.path.exists(entry):
+ raise Exception, 'Target "%s" already exists' % entry
+
+ for filespec in filespecs:
+ filespec = filespec.rstrip('/')
+ basename = '/' + os.path.basename(filespec)
+ __copy_singlefile(filespec, target, basename)
+
+ elif os.path.exists(target):
+ raise Exception, 'Target "%s" exists but is not a directory' % target
+ elif len(filespecs) != 1:
+ raise Exception, 'Cannot copy more than one file to non-directory'
+
+ else:
+ # at this point: len(filespecs)==1 and target does not exist
+
+ # check target directory
+ targetdir = os.path.dirname(target)
+ if targetdir != '' and not os.path.isdir(targetdir):
+ raise Exception, 'Target directory "%s" does not exist' % targetdir
+
+ __copy_singlefile(filespecs[0].rstrip('/'), target)
+
+## main
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
+except getopt.GetoptError:
+ usage()
+
+for o, a in opts:
+ if o in ("-h", "--help"):
+ usage()
+
+try:
+ copy(args[0:-1], args[-1])
+except Exception, ex:
+ print "git-cp error: %s" % ex
+ sys.exit(1)
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [RFC PATCH] Add new git-cp command, transposed from stgit.
2007-05-17 20:49 [RFC PATCH] Add new git-cp command, transposed from stgit Yann Dirson
@ 2007-05-18 7:57 ` Karl Hasselström
0 siblings, 0 replies; 2+ messages in thread
From: Karl Hasselström @ 2007-05-18 7:57 UTC (permalink / raw)
To: Yann Dirson; +Cc: git
On 2007-05-17 22:49:00 +0200, Yann Dirson wrote:
> A known annoying limitation of this version (very quickly adapted)
> is that quoted files in the "git ls-files" output trigger the
> assert() clause. I'd use "-z", but it looks like noone wrote a
> zero-separated file reader for python (how that makes me regret perl
> ;).
>
> I can surely write one, but do we want this to be in python after
> all ? At least in perl it would be easy to fix this issue, but do we
> even accept perl scripts for such features ? OTOH, I'm not sure it
> is worth rewriting in C...
I was under the impression that perl was somewhat acceptable, while
python is not used in git anymore?
--
Karl Hasselström, kha@treskal.com
www.treskal.com/kalle
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2007-05-18 7:57 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-17 20:49 [RFC PATCH] Add new git-cp command, transposed from stgit Yann Dirson
2007-05-18 7:57 ` Karl Hasselström
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox