git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Pete Wyckoff <pw@padd.com>
To: Sam Hocevar <sam@zoy.org>
Cc: git@vger.kernel.org
Subject: Re: git-p4 workflow suggestions?
Date: Tue, 17 Mar 2009 08:18:15 -0700	[thread overview]
Message-ID: <20090317151815.GA2451@padd.com> (raw)
In-Reply-To: <20090316180108.GE27280@zoy.org>

sam@zoy.org wrote on Mon, 16 Mar 2009 19:01 +0100:
>    Yes, like this. More precisely:
> 
>     //work/framework/example/... //client/...
>     //work/project1/src/...  //client/src/...
>     //work/project1/include/...  //client/include/...
[..]
>    My changes are extremely messy but I will refactor them as time goes.
> There is at least one other important thing my git-p4 does, which is not
> storing the whole commit in memory. Combined with the patches I sent
> last week to this list, it's the only way I can import the p4 repository
> we have at work. (See http://zoy.org/~sam/git/clumsily-hacked-git-p4)

Oh, that is, ahem, a bit site-specific.  The looping over chunks in
the import phase is important, and other people have been thinking
about that.  I'll ignore that aspect for now, though, and we'll see
if we can get the client-spec part worked out.

Can you take a look at the attached.  Its goal is purely to allow
you to clone a complex spec like yours above.  You may have to merge
this in with your perrformance changes.

Edit your ~/.gitconfig to add a section:

	[git-p4]
		useClientSpec = true

Then copy a good P4ENV from a p4 client that has a client spec
checked out as you like.  git-p4 clone will do "p4 client -o",
reading that spec, and use the results to import, hopefully as
you have things laid out in the spec.

If this seems to work for you, we can figure out how to clean up
the patch so it can be used generally by people with and without
client specs.

		-- Pete

---------
From 4a922efcef18e3bb740f88c31ed4d00fa66f4cce Mon Sep 17 00:00:00 2001
From: Pete Wyckoff <petew@netapp.com>
Date: Wed, 26 Nov 2008 12:28:09 -0500
Subject: [PATCH] honor git client spec

Destination directories for parts of the depot are specified in the
client spec.  Use them as given.  Also read the entire client spec to
figure out what to do.
---
 contrib/fast-import/git-p4 |  110 ++++++++++++++++++++++++++++++++++---------
 1 files changed, 87 insertions(+), 23 deletions(-)

diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4
index 332c7f8..d953a1e 100755
--- a/contrib/fast-import/git-p4
+++ b/contrib/fast-import/git-p4
@@ -451,6 +451,26 @@ def p4ChangesForPaths(depotPaths, changeRange):
     changelist.sort()
     return changelist
 
+#
+# Sort by number of slashes first:  more specific at the top.  Then
+# sort by alpha within a given number of path components.
+#
+def clientSortFunc(a, b):
+    asrc = a[0]
+    bsrc = b[0]
+    asrclen = asrc.count("/")
+    bsrclen = bsrc.count("/")
+    if asrclen > bsrclen:
+	return -1
+    elif asrclen < bsrclen:
+	return 1
+    elif asrc > bsrc:
+	return 1
+    elif asrc < bsrc:
+	return -1
+    else:
+	return 0
+
 class Command:
     def __init__(self):
         self.usage = "usage: %prog [options]"
@@ -959,8 +979,9 @@ class P4Sync(Command):
             includeFile = True
             for val in self.clientSpecDirs:
                 if f['path'].startswith(val[0]):
-                    if val[1] <= 0:
+                    if val[1] == '-':
                         includeFile = False
+		    f['pathmap'] = val
                     break
 
             if includeFile:
@@ -1056,7 +1077,12 @@ class P4Sync(Command):
                 print "\nfile %s is a strange apple file that forks. Ignoring!" % file['path']
                 continue
 
-            relPath = self.stripRepoPath(file['path'], branchPrefixes)
+	    if 'pathmap' in file:
+		relPath = file['pathmap'][1] + file['path'][len(file['pathmap'][0]):]
+	    else:
+		relPath = self.stripRepoPath(file['path'], branchPrefixes)
+
+	    print "path", file['path'], "->", relPath
             if file["action"] in ("delete", "purge"):
                 self.gitStream.write("D %s\n" % relPath)
             else:
@@ -1439,24 +1465,54 @@ class P4Sync(Command):
 
 
     def getClientSpec(self):
-        specList = p4CmdList( "client -o" )
+        specList = p4CmdList("client -o")
         temp = {}
+	client = ""
+        for entry in specList:
+            for k,v in entry.iteritems():
+		if k.startswith("Client"):
+		    client = v
+		    print "client is", client
+	if not client:
+	    sys.stderr.write("no client found\n")
+	    sys.exit(1)
+	client = "//" + client + "/"
         for entry in specList:
             for k,v in entry.iteritems():
                 if k.startswith("View"):
-                    if v.startswith('"'):
-                        start = 1
-                    else:
-                        start = 0
-                    index = v.find("...")
-                    v = v[start:index]
-                    if v.startswith("-"):
-                        v = v[1:]
-                        temp[v] = -len(v)
-                    else:
-                        temp[v] = len(v)
-        self.clientSpecDirs = temp.items()
-        self.clientSpecDirs.sort( lambda x, y: abs( y[1] ) - abs( x[1] ) )
+		    if v.startswith('"'):
+			v = v[1:]
+		    if v.endswith('"'):
+			v = v[:-1]
+		    d = v.split(" ");
+		    if len(d) != 2:
+			sys.stderr.write( \
+			    "expecting two fields in view, got: %s\n" % v)
+			sys.exit(1)
+		    if not d[0].endswith("..."):
+			sys.stderr.write(\
+			    "expecting trailing ..., got: %s\n" % d[0])
+			sys.exit(1)
+		    d[0] = d[0][:-3]
+		    if not d[1].endswith("..."):
+			sys.stderr.write(\
+			    "expecting trailing ..., got: %s\n" % d[1])
+			sys.exit(1)
+		    d[1] = d[1][:-3]
+		    if not d[1].startswith(client):
+			sys.stderr.write(\
+			    "expecting dest to start with %s, got: %s\n" % \
+			    (client, d[1]))
+			sys.exit(1)
+		    d[1] = d[1][len(client):]
+		    # negated items do not appear in tree
+		    if d[0].startswith("-"):
+			d[0] = d[0][1:]
+			d[1] = ""
+		    temp[d[0]] = d[1]
+
+	self.clientSpecDirs = temp.items()
+	self.clientSpecDirs.sort(clientSortFunc)
 
     def run(self, args):
         self.depotPaths = []
@@ -1718,7 +1774,7 @@ class P4Clone(P4Sync):
     def __init__(self):
         P4Sync.__init__(self)
         self.description = "Creates a new git repository and imports from Perforce into it"
-        self.usage = "usage: %prog [options] //depot/path[@revRange]"
+        self.usage = "usage: %prog [options] [//depot/path[@revRange]]"
         self.options += [
             optparse.make_option("--destination", dest="cloneDestination",
                                  action='store', default=None,
@@ -1746,18 +1802,26 @@ class P4Clone(P4Sync):
         return os.path.split(depotDir)[1]
 
     def run(self, args):
-        if len(args) < 1:
-            return False
-
         if self.keepRepoPath and not self.cloneDestination:
             sys.stderr.write("Must specify destination for --keep-path\n")
             sys.exit(1)
 
         depotPaths = args
 
-        if not self.cloneDestination and len(depotPaths) > 1:
-            self.cloneDestination = depotPaths[-1]
-            depotPaths = depotPaths[:-1]
+	if gitConfig("git-p4.useclientspec") == "true":
+	    if not os.path.exists("P4ENV"):
+		sys.stderr.write("Must copy P4ENV file from a valid client\n")
+		sys.exit(1)
+	    self.getClientSpec()
+	    if not depotPaths:
+		depotPaths = [p[0] for p in self.clientSpecDirs]
+	else:
+	    if not depotPaths:
+		sys.stderr.write("Must specify depot path if no client spec\n")
+		sys.exit(1)
+
+        if not self.cloneDestination:
+		self.cloneDestination = "."
 
         self.cloneExclude = ["/"+p for p in self.cloneExclude]
         for p in depotPaths:
-- 
1.6.0.6

  reply	other threads:[~2009-03-17 15:18 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-09 14:21 git-p4 workflow suggestions? Sam Hocevar
2009-03-10  7:15 ` Christian Couder
2009-03-10  9:57   ` Sam Hocevar
2009-03-11  7:03     ` Christian Couder
2009-03-11 12:58 ` Pete Wyckoff
2009-03-16 18:01   ` Sam Hocevar
2009-03-17 15:18     ` Pete Wyckoff [this message]
2009-03-20 10:31       ` Sam Hocevar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090317151815.GA2451@padd.com \
    --to=pw@padd.com \
    --cc=git@vger.kernel.org \
    --cc=sam@zoy.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).