{"thread":{"id":"12179","subject":"[PATCH RFC] git-p4: Support usage of perforce client spec","startedAt":"2008-02-18T14:22:08Z","lastAt":"2008-02-18T14:22:08Z","messageCount":1,"participants":["Tor Arvid Lund"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"69155","messageId":"1203344528-10981-1-git-send-email-torarvid@gmail.com","threadId":"12179","inReplyTo":null,"subject":"[PATCH RFC] git-p4: Support usage of perforce client spec","fromName":"Tor Arvid Lund","fromEmail":"torarvid@gmail.com","sentAt":"2008-02-18T14:22:08Z","receivedAt":"2008-02-18T14:22:08Z","isPatch":true,"sender":{"key":"torarvid@gmail.com","avatar":"https://avatars.githubusercontent.com/u/439758?v=4"},"body":"When syncing, git-p4 will only download files that are included in the active\nperforce client spec. This does not change the default behaviour - it requires\nthat the user either supplies the command line argument --use-client-spec, or\nsets the git config option p4.useclientspec to \"true\".\n\nSigned-off-by: Tor Arvid Lund <torarvid@gmail.com>\n---\n\nThis is something I use personally to help reduce the size downloaded when\ncloning and syncing, as the Perforce depot i normally use is littered with\nchangelists that are much bigger than they should (and thus contain both\ninteresting and uninteresting files). I thought it might be of use to other\npeople too.\n\nNote that this is my first attempt at git-related hacking (and that I am also a\nPython novice), so it may very well need some tuning/fixing before it is any\ngood.\n\n contrib/fast-import/git-p4 |   50 ++++++++++++++++++++++++++++++++++++-------\n 1 files changed, 42 insertions(+), 8 deletions(-)\n\ndiff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4\nindex 781a0cb..e3766c3 100755\n--- a/contrib/fast-import/git-p4\n+++ b/contrib/fast-import/git-p4\n@@ -817,7 +817,9 @@ class P4Sync(Command):\n                                      help=\"Import into refs/heads/ , not refs/remotes\"),\n                 optparse.make_option(\"--max-changes\", dest=\"maxChanges\"),\n                 optparse.make_option(\"--keep-path\", dest=\"keepRepoPath\", action='store_true',\n-                                     help=\"Keep entire BRANCH/DIR/SUBDIR prefix during import\")\n+                                     help=\"Keep entire BRANCH/DIR/SUBDIR prefix during import\"),\n+                optparse.make_option(\"--use-client-spec\", dest=\"useClientSpec\", action='store_true',\n+                                     help=\"Only sync files that are included in the Perforce Client Spec\")\n         ]\n         self.description = \"\"\"Imports from Perforce into a git repository.\\n\n     example:\n@@ -843,6 +845,8 @@ class P4Sync(Command):\n         self.keepRepoPath = False\n         self.depotPaths = None\n         self.p4BranchesInGit = []\n+        self.useClientSpec = False\n+        self.clientSpecDirs = []\n \n         if gitConfig(\"git-p4.syncFromOrigin\") == \"false\":\n             self.syncWithOrigin = False\n@@ -911,11 +915,21 @@ class P4Sync(Command):\n \n     ## Should move this out, doesn't use SELF.\n     def readP4Files(self, files):\n+        for f in files:\n+            for val in self.clientSpecDirs:\n+                if f['path'].startswith(val[0]):\n+                    if val[1] > 0:\n+                        f['include'] = True\n+                    else:\n+                        f['include'] = False\n+                    break\n+\n         files = [f for f in files\n-                 if f['action'] != 'delete']\n+                 if f['action'] != 'delete' and\n+                 (f.has_key('include') == False or f['include'] == True)]\n \n         if not files:\n-            return\n+            return []\n \n         filedata = p4CmdList('-x - print',\n                              stdin='\\n'.join(['%s#%s' % (f['path'], f['rev'])\n@@ -950,6 +964,7 @@ class P4Sync(Command):\n         for f in files:\n             assert not f.has_key('data')\n             f['data'] = contents[f['path']]\n+        return files\n \n     def commit(self, details, files, branch, branchPrefixes, parent = \"\"):\n         epoch = details[\"time\"]\n@@ -966,11 +981,7 @@ class P4Sync(Command):\n                 new_files.append (f)\n             else:\n                 sys.stderr.write(\"Ignoring file outside of prefix: %s\\n\" % path)\n-        files = new_files\n-        self.readP4Files(files)\n-\n-\n-\n+        files = self.readP4Files(new_files)\n \n         self.gitStream.write(\"commit %s\\n\" % branch)\n #        gitStream.write(\"mark :%s\\n\" % details[\"change\"])\n@@ -1385,6 +1396,26 @@ class P4Sync(Command):\n             print self.gitError.read()\n \n \n+    def getClientSpec(self):\n+        specList = p4CmdList( \"client -o\" )\n+        temp = {}\n+        for entry in specList:\n+            for k,v in entry.iteritems():\n+                if k.startswith(\"View\"):\n+                    if v.startswith('\"'):\n+                        start = 1\n+                    else:\n+                        start = 0\n+                    index = v.find(\"...\")\n+                    v = v[start:index]\n+                    if v.startswith(\"-\"):\n+                        v = v[1:]\n+                        temp[v] = -len(v)\n+                    else:\n+                        temp[v] = len(v)\n+        self.clientSpecDirs = temp.items()\n+        self.clientSpecDirs.sort( lambda x, y: abs( y[1] ) - abs( x[1] ) )\n+\n     def run(self, args):\n         self.depotPaths = []\n         self.changeRange = \"\"\n@@ -1417,6 +1448,9 @@ class P4Sync(Command):\n             if not gitBranchExists(self.refPrefix + \"HEAD\") and self.importIntoRemotes and gitBranchExists(self.branch):\n                 system(\"git symbolic-ref %sHEAD %s\" % (self.refPrefix, self.branch))\n \n+        if self.useClientSpec or gitConfig(\"p4.useclientspec\") == \"true\":\n+            self.getClientSpec()\n+\n         # TODO: should always look at previous commits,\n         # merge with previous imports, if possible.\n         if args == []:\n-- \n1.5.4.35.g9d0ca\n"}]}