X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=contrib%2Ffast-import%2Fgit-p4;h=342529db309821f461e8f77d05bc5e01c76802ec;hb=17e46ea6fea5273b51b424a8016f9da3412792d4;hp=d8de9f6c255ca7e458eac62e7f14b3d664054587;hpb=92798702cf6d201f80e257a07d0a0c40565c79fe;p=git.git diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index d8de9f6c2..342529db3 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -16,6 +16,46 @@ from sets import Set; verbose = False + +def p4_build_cmd(cmd): + """Build a suitable p4 command line. + + This consolidates building and returning a p4 command line into one + location. It means that hooking into the environment, or other configuration + can be done more easily. + """ + real_cmd = "%s " % "p4" + + user = gitConfig("git-p4.user") + if len(user) > 0: + real_cmd += "-u %s " % user + + password = gitConfig("git-p4.password") + if len(password) > 0: + real_cmd += "-P %s " % password + + port = gitConfig("git-p4.port") + if len(port) > 0: + real_cmd += "-p %s " % port + + host = gitConfig("git-p4.host") + if len(host) > 0: + real_cmd += "-h %s " % host + + client = gitConfig("git-p4.client") + if len(client) > 0: + real_cmd += "-c %s " % client + + real_cmd += "%s" % (cmd) + if verbose: + print real_cmd + return real_cmd + +def chdir(dir): + if os.name == 'nt': + os.environ['PWD']=dir + os.chdir(dir) + def die(msg): if verbose: raise Exception(msg) @@ -34,6 +74,10 @@ def write_pipe(c, str): return val +def p4_write_pipe(c, str): + real_cmd = p4_build_cmd(c) + return write_pipe(real_cmd, str) + def read_pipe(c, ignore_error=False): if verbose: sys.stderr.write('Reading pipe: %s\n' % c) @@ -45,6 +89,9 @@ def read_pipe(c, ignore_error=False): return val +def p4_read_pipe(c, ignore_error=False): + real_cmd = p4_build_cmd(c) + return read_pipe(real_cmd, ignore_error) def read_pipe_lines(c): if verbose: @@ -57,12 +104,22 @@ def read_pipe_lines(c): return val +def p4_read_pipe_lines(c): + """Specifically invoke p4 on the command supplied. """ + real_cmd = p4_build_cmd(c) + return read_pipe_lines(real_cmd) + def system(cmd): if verbose: sys.stderr.write("executing %s\n" % cmd) if os.system(cmd) != 0: die("command failed: %s" % cmd) +def p4_system(cmd): + """Specifically invoke p4 as the system command. """ + real_cmd = p4_build_cmd(cmd) + return system(real_cmd) + def isP4Exec(kind): """Determine if a Perforce 'kind' should have execute permission @@ -84,12 +141,12 @@ def setP4ExecBit(file, mode): if p4Type[-1] == "+": p4Type = p4Type[0:-1] - system("p4 reopen -t %s %s" % (p4Type, file)) + p4_system("reopen -t %s %s" % (p4Type, file)) def getP4OpenedType(file): # Returns the perforce file type for the given file. - result = read_pipe("p4 opened %s" % file) + result = p4_read_pipe("opened %s" % file) match = re.match(".*\((.+)\)\r?$", result) if match: return match.group(1) @@ -145,7 +202,7 @@ def isModeExecChanged(src_mode, dst_mode): return isModeExec(src_mode) != isModeExec(dst_mode) def p4CmdList(cmd, stdin=None, stdin_mode='w+b'): - cmd = "p4 -G %s" % cmd + cmd = p4_build_cmd("-G %s" % (cmd)) if verbose: sys.stderr.write("Opening pipe: %s\n" % cmd) @@ -188,7 +245,22 @@ def p4Cmd(cmd): def p4Where(depotPath): if not depotPath.endswith("/"): depotPath += "/" - output = p4Cmd("where %s..." % depotPath) + depotPath = depotPath + "..." + outputList = p4CmdList("where %s" % depotPath) + output = None + for entry in outputList: + if "depotFile" in entry: + if entry["depotFile"] == depotPath: + output = entry + break + elif "data" in entry: + data = entry.get("data") + space = data.find(" ") + if data[:space] == depotPath: + output = entry + break + if output == None: + return "" if output["code"] == "error": return "" clientPath = "" @@ -259,8 +331,11 @@ def gitBranchExists(branch): stderr=subprocess.PIPE, stdout=subprocess.PIPE); return proc.wait() == 0; +_gitConfig = {} def gitConfig(key): - return read_pipe("git config %s" % key, ignore_error=True).strip() + if not _gitConfig.has_key(key): + _gitConfig[key] = read_pipe("git config %s" % key, ignore_error=True).strip() + return _gitConfig[key] def p4BranchesInGit(branchesAreInRemotes = True): branches = {} @@ -364,16 +439,17 @@ def originP4BranchesExist(): def p4ChangesForPaths(depotPaths, changeRange): assert depotPaths - output = read_pipe_lines("p4 changes " + ' '.join (["%s...%s" % (p, changeRange) + output = p4_read_pipe_lines("changes " + ' '.join (["%s...%s" % (p, changeRange) for p in depotPaths])) - changes = [] + changes = {} for line in output: - changeNum = line.split(" ")[1] - changes.append(int(changeNum)) + changeNum = int(line.split(" ")[1]) + changes[changeNum] = True - changes.sort() - return changes + changelist = changes.keys() + changelist.sort() + return changelist class Command: def __init__(self): @@ -512,7 +588,7 @@ class P4Submit(Command): # remove lines in the Files section that show changes to files outside the depot path we're committing into template = "" inFilesSection = False - for line in read_pipe_lines("p4 change -o"): + for line in p4_read_pipe_lines("change -o"): if line.endswith("\r\n"): line = line[:-2] + "\n" if inFilesSection: @@ -547,7 +623,7 @@ class P4Submit(Command): modifier = diff['status'] path = diff['src'] if modifier == "M": - system("p4 edit \"%s\"" % path) + p4_system("edit \"%s\"" % path) if isModeExecChanged(diff['src_mode'], diff['dst_mode']): filesToChangeExecBit[path] = diff['dst_mode'] editedFiles.add(path) @@ -562,8 +638,8 @@ class P4Submit(Command): filesToAdd.remove(path) elif modifier == "R": src, dest = diff['src'], diff['dst'] - system("p4 integrate -Dt \"%s\" \"%s\"" % (src, dest)) - system("p4 edit \"%s\"" % (dest)) + p4_system("integrate -Dt \"%s\" \"%s\"" % (src, dest)) + p4_system("edit \"%s\"" % (dest)) if isModeExecChanged(diff['src_mode'], diff['dst_mode']): filesToChangeExecBit[dest] = diff['dst_mode'] os.unlink(dest) @@ -587,7 +663,7 @@ class P4Submit(Command): if response == "s": print "Skipping! Good luck with the next patches..." for f in editedFiles: - system("p4 revert \"%s\"" % f); + p4_system("revert \"%s\"" % f); for f in filesToAdd: system("rm %s" %f) return @@ -610,10 +686,10 @@ class P4Submit(Command): system(applyPatchCmd) for f in filesToAdd: - system("p4 add \"%s\"" % f) + p4_system("add \"%s\"" % f) for f in filesToDelete: - system("p4 revert \"%s\"" % f) - system("p4 delete \"%s\"" % f) + p4_system("revert \"%s\"" % f) + p4_system("delete \"%s\"" % f) # Set/clear executable bits for f in filesToChangeExecBit.keys(): @@ -629,7 +705,7 @@ class P4Submit(Command): submitTemplate = self.prepareLogMessage(template, logMessage) if os.environ.has_key("P4DIFF"): del(os.environ["P4DIFF"]) - diff = read_pipe("p4 diff -du ...") + diff = p4_read_pipe("diff -du ...") newdiff = "" for newFile in filesToAdd: @@ -651,6 +727,7 @@ class P4Submit(Command): newdiff = newdiff.replace("\n", "\r\n") tmpFile.write(submitTemplate + separatorLine + diff + newdiff) tmpFile.close() + mtime = os.stat(fileName).st_mtime defaultEditor = "vi" if platform.system() == "Windows": defaultEditor = "notepad" @@ -659,15 +736,29 @@ class P4Submit(Command): else: editor = os.environ.get("EDITOR", defaultEditor); system(editor + " " + fileName) - tmpFile = open(fileName, "rb") - message = tmpFile.read() - tmpFile.close() - os.remove(fileName) - submitTemplate = message[:message.index(separatorLine)] - if self.isWindows: - submitTemplate = submitTemplate.replace("\r\n", "\n") - write_pipe("p4 submit -i", submitTemplate) + response = "y" + if os.stat(fileName).st_mtime <= mtime: + response = "x" + while response != "y" and response != "n": + response = raw_input("Submit template unchanged. Submit anyway? [y]es, [n]o (skip this patch) ") + + if response == "y": + tmpFile = open(fileName, "rb") + message = tmpFile.read() + tmpFile.close() + submitTemplate = message[:message.index(separatorLine)] + if self.isWindows: + submitTemplate = submitTemplate.replace("\r\n", "\n") + p4_write_pipe("submit -i", submitTemplate) + else: + for f in editedFiles: + p4_system("revert \"%s\"" % f); + for f in filesToAdd: + p4_system("revert \"%s\"" % f); + system("rm %s" %f) + + os.remove(fileName) else: fileName = "submit.txt" file = open(fileName, "w+") @@ -687,6 +778,10 @@ class P4Submit(Command): else: return False + allowSubmit = gitConfig("git-p4.allowSubmit") + if len(allowSubmit) > 0 and not self.master in allowSubmit.split(","): + die("%s is not in git-p4.allowSubmit" % self.master) + [upstream, settings] = findUpstreamBranchPoint() self.depotPath = settings['depot-paths'][0] if len(self.origin) == 0: @@ -708,9 +803,9 @@ class P4Submit(Command): print "Perforce checkout for depot path %s located at %s" % (self.depotPath, self.clientPath) self.oldWorkingDirectory = os.getcwd() - os.chdir(self.clientPath) + chdir(self.clientPath) print "Syncronizing p4 checkout..." - system("p4 sync ...") + p4_system("sync ...") self.check() @@ -728,7 +823,7 @@ class P4Submit(Command): if len(commits) == 0: print "All changes applied!" - os.chdir(self.oldWorkingDirectory) + chdir(self.oldWorkingDirectory) sync = P4Sync() sync.run([]) @@ -870,7 +965,7 @@ class P4Sync(Command): if includeFile: filesForCommit.append(f) - if f['action'] != 'delete': + if f['action'] not in ('delete', 'purge'): filesToRead.append(f) filedata = [] @@ -889,11 +984,11 @@ class P4Sync(Command): while j < len(filedata): stat = filedata[j] j += 1 - text = []; + text = '' while j < len(filedata) and filedata[j]['code'] in ('text', 'unicode', 'binary'): - text.append(filedata[j]['data']) + text += filedata[j]['data'] + del filedata[j]['data'] j += 1 - text = ''.join(text) if not stat.has_key('depotFile'): sys.stderr.write("p4 print fails with: %s\n" % repr(stat)) @@ -902,7 +997,7 @@ class P4Sync(Command): if stat['type'] in ('text+ko', 'unicode+ko', 'binary+ko'): text = re.sub(r'(?i)\$(Id|Header):[^$]*\$',r'$\1$', text) elif stat['type'] in ('text+k', 'ktext', 'kxtext', 'unicode+k', 'binary+k'): - text = re.sub(r'(?i)\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$',r'$\1$', text) + text = re.sub(r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$\n]*\$',r'$\1$', text) contents[stat['depotFile']] = text @@ -962,7 +1057,7 @@ class P4Sync(Command): continue relPath = self.stripRepoPath(file['path'], branchPrefixes) - if file["action"] == "delete": + if file["action"] in ("delete", "purge"): self.gitStream.write("D %s\n" % relPath) else: data = file['data'] @@ -1001,7 +1096,7 @@ class P4Sync(Command): cleanedFiles = {} for info in files: - if info["action"] == "delete": + if info["action"] in ("delete", "purge"): continue cleanedFiles[info["depotFile"]] = info["rev"] @@ -1047,7 +1142,7 @@ class P4Sync(Command): s = '' for (key, val) in self.users.items(): - s += "%s\t%s\n" % (key, val) + s += "%s\t%s\n" % (key.expandtabs(1), val.expandtabs(1)) open(self.getUserCacheFilename(), "wb").write(s) self.userMapFromPerforceServer = True @@ -1324,7 +1419,7 @@ class P4Sync(Command): if change > newestRevision: newestRevision = change - if info["action"] == "delete": + if info["action"] in ("delete", "purge"): # don't increase the file cnt, otherwise details["depotFile123"] will have gaps! #fileCnt = fileCnt + 1 continue @@ -1395,7 +1490,7 @@ class P4Sync(Command): if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes and gitBranchExists(self.branch): system("git symbolic-ref %sHEAD %s" % (self.refPrefix, self.branch)) - if self.useClientSpec or gitConfig("p4.useclientspec") == "true": + if self.useClientSpec or gitConfig("git-p4.useclientspec") == "true": self.getClientSpec() # TODO: should always look at previous commits, @@ -1666,14 +1761,18 @@ class P4Clone(P4Sync): print "Importing from %s into %s" % (', '.join(depotPaths), self.cloneDestination) if not os.path.exists(self.cloneDestination): os.makedirs(self.cloneDestination) - os.chdir(self.cloneDestination) + chdir(self.cloneDestination) system("git init") self.gitdir = os.getcwd() + "/.git" if not P4Sync.run(self, depotPaths): return False if self.branch != "master": - if gitBranchExists("refs/remotes/p4/master"): - system("git branch master refs/remotes/p4/master") + if self.importIntoRemotes: + masterbranch = "refs/remotes/p4/master" + else: + masterbranch = "refs/heads/p4/master" + if gitBranchExists(masterbranch): + system("git branch master %s" % masterbranch) system("git checkout -f") else: print "Could not detect main branch. No checkout/master branch created." @@ -1778,7 +1877,7 @@ def main(): if os.path.exists(cmd.gitdir): cdup = read_pipe("git rev-parse --show-cdup").strip() if len(cdup) > 0: - os.chdir(cdup); + chdir(cdup); if not isValidGitDir(cmd.gitdir): if isValidGitDir(cmd.gitdir + "/.git"):