Browse Source

Merge branch 'pw/p4'

* pw/p4:
  git-p4: support clone --bare
  git-p4: decode p4 wildcard characters
  git-p4: better message for "git-p4 sync" when not cloned
  git-p4: reinterpret confusing p4 message
  git-p4: accommodate new move/delete type in p4
  git-p4: add missing newline in initial import message
  git-p4: fix key error for p4 problem
  git-p4: test script
maint
Junio C Hamano 14 years ago
parent
commit
8d3a362028
  1. 58
      contrib/fast-import/git-p4
  2. 100
      t/t9800-git-p4.sh

58
contrib/fast-import/git-p4

@ -834,6 +834,8 @@ class P4Submit(Command):
return True return True


class P4Sync(Command): class P4Sync(Command):
delete_actions = ( "delete", "move/delete", "purge" )

def __init__(self): def __init__(self):
Command.__init__(self) Command.__init__(self)
self.options = [ self.options = [
@ -882,6 +884,23 @@ class P4Sync(Command):
if gitConfig("git-p4.syncFromOrigin") == "false": if gitConfig("git-p4.syncFromOrigin") == "false":
self.syncWithOrigin = False self.syncWithOrigin = False


#
# P4 wildcards are not allowed in filenames. P4 complains
# if you simply add them, but you can force it with "-f", in
# which case it translates them into %xx encoding internally.
# Search for and fix just these four characters. Do % last so
# that fixing it does not inadvertently create new %-escapes.
#
def wildcard_decode(self, path):
# Cannot have * in a filename in windows; untested as to
# what p4 would do in such a case.
if not self.isWindows:
path = path.replace("%2A", "*")
path = path.replace("%23", "#") \
.replace("%40", "@") \
.replace("%25", "%")
return path

def extractFilesFromCommit(self, commit): def extractFilesFromCommit(self, commit):
self.cloneExclude = [re.sub(r"\.\.\.$", "", path) self.cloneExclude = [re.sub(r"\.\.\.$", "", path)
for path in self.cloneExclude] for path in self.cloneExclude]
@ -976,6 +995,7 @@ class P4Sync(Command):
return return


relPath = self.stripRepoPath(file['depotFile'], self.branchPrefixes) relPath = self.stripRepoPath(file['depotFile'], self.branchPrefixes)
relPath = self.wildcard_decode(relPath)
if verbose: if verbose:
sys.stderr.write("%s\n" % relPath) sys.stderr.write("%s\n" % relPath)


@ -1054,10 +1074,10 @@ class P4Sync(Command):


if includeFile: if includeFile:
filesForCommit.append(f) filesForCommit.append(f)
if f['action'] not in ('delete', 'move/delete', 'purge'): if f['action'] in self.delete_actions:
filesToRead.append(f)
else:
filesToDelete.append(f) filesToDelete.append(f)
else:
filesToRead.append(f)


# deleted files... # deleted files...
for f in filesToDelete: for f in filesToDelete:
@ -1143,7 +1163,7 @@ class P4Sync(Command):


cleanedFiles = {} cleanedFiles = {}
for info in files: for info in files:
if info["action"] in ("delete", "purge"): if info["action"] in self.delete_actions:
continue continue
cleanedFiles[info["depotFile"]] = info["rev"] cleanedFiles[info["depotFile"]] = info["rev"]


@ -1445,7 +1465,7 @@ class P4Sync(Command):
print "Doing initial import of %s from revision %s into %s" % (' '.join(self.depotPaths), revision, self.branch) print "Doing initial import of %s from revision %s into %s" % (' '.join(self.depotPaths), revision, self.branch)


details = { "user" : "git perforce import user", "time" : int(time.time()) } details = { "user" : "git perforce import user", "time" : int(time.time()) }
details["desc"] = ("Initial import of %s from the state at revision %s" details["desc"] = ("Initial import of %s from the state at revision %s\n"
% (' '.join(self.depotPaths), revision)) % (' '.join(self.depotPaths), revision))
details["change"] = revision details["change"] = revision
newestRevision = 0 newestRevision = 0
@ -1456,9 +1476,16 @@ class P4Sync(Command):
% (p, revision) % (p, revision)
for p in self.depotPaths])): for p in self.depotPaths])):


if info['code'] == 'error': if 'code' in info and info['code'] == 'error':
sys.stderr.write("p4 returned an error: %s\n" sys.stderr.write("p4 returned an error: %s\n"
% info['data']) % info['data'])
if info['data'].find("must refer to client") >= 0:
sys.stderr.write("This particular p4 error is misleading.\n")
sys.stderr.write("Perhaps the depot path was misspelled.\n");
sys.stderr.write("Depot path: %s\n" % " ".join(self.depotPaths))
sys.exit(1)
if 'p4ExitCode' in info:
sys.stderr.write("p4 exitcode: %s\n" % info['p4ExitCode'])
sys.exit(1) sys.exit(1)




@ -1466,7 +1493,7 @@ class P4Sync(Command):
if change > newestRevision: if change > newestRevision:
newestRevision = change newestRevision = change


if info["action"] in ("delete", "purge"): if info["action"] in self.delete_actions:
# don't increase the file cnt, otherwise details["depotFile123"] will have gaps! # don't increase the file cnt, otherwise details["depotFile123"] will have gaps!
#fileCnt = fileCnt + 1 #fileCnt = fileCnt + 1
continue continue
@ -1709,6 +1736,8 @@ class P4Sync(Command):


changes.sort() changes.sort()
else: else:
if not self.p4BranchesInGit:
die("No remote p4 branches. Perhaps you never did \"git p4 clone\" in here.");
if self.verbose: if self.verbose:
print "Getting p4 changes for %s...%s" % (', '.join(self.depotPaths), print "Getting p4 changes for %s...%s" % (', '.join(self.depotPaths),
self.changeRange) self.changeRange)
@ -1789,10 +1818,13 @@ class P4Clone(P4Sync):
help="where to leave result of the clone"), help="where to leave result of the clone"),
optparse.make_option("-/", dest="cloneExclude", optparse.make_option("-/", dest="cloneExclude",
action="append", type="string", action="append", type="string",
help="exclude depot path") help="exclude depot path"),
optparse.make_option("--bare", dest="cloneBare",
action="store_true", default=False),
] ]
self.cloneDestination = None self.cloneDestination = None
self.needsGit = False self.needsGit = False
self.cloneBare = False


# This is required for the "append" cloneExclude action # This is required for the "append" cloneExclude action
def ensure_value(self, attr, value): def ensure_value(self, attr, value):
@ -1832,11 +1864,16 @@ class P4Clone(P4Sync):
self.cloneDestination = self.defaultDestination(args) self.cloneDestination = self.defaultDestination(args)


print "Importing from %s into %s" % (', '.join(depotPaths), self.cloneDestination) print "Importing from %s into %s" % (', '.join(depotPaths), self.cloneDestination)

if not os.path.exists(self.cloneDestination): if not os.path.exists(self.cloneDestination):
os.makedirs(self.cloneDestination) os.makedirs(self.cloneDestination)
chdir(self.cloneDestination) chdir(self.cloneDestination)
system("git init")
self.gitdir = os.getcwd() + "/.git" init_cmd = [ "git", "init" ]
if self.cloneBare:
init_cmd.append("--bare")
subprocess.check_call(init_cmd)

if not P4Sync.run(self, depotPaths): if not P4Sync.run(self, depotPaths):
return False return False
if self.branch != "master": if self.branch != "master":
@ -1846,6 +1883,7 @@ class P4Clone(P4Sync):
masterbranch = "refs/heads/p4/master" masterbranch = "refs/heads/p4/master"
if gitBranchExists(masterbranch): if gitBranchExists(masterbranch):
system("git branch master %s" % masterbranch) system("git branch master %s" % masterbranch)
if not self.cloneBare:
system("git checkout -f") system("git checkout -f")
else: else:
print "Could not detect main branch. No checkout/master branch created." print "Could not detect main branch. No checkout/master branch created."

100
t/t9800-git-p4.sh

@ -0,0 +1,100 @@
#!/bin/sh

test_description='git-p4 tests'

. ./test-lib.sh

( p4 -h && p4d -h ) >/dev/null 2>&1 || {
skip_all='skipping git-p4 tests; no p4 or p4d'
test_done
}

GITP4=$GIT_BUILD_DIR/contrib/fast-import/git-p4
P4DPORT=10669

db="$TRASH_DIRECTORY/db"
cli="$TRASH_DIRECTORY/cli"
git="$TRASH_DIRECTORY/git"

test_debug 'echo p4d -q -d -r "$db" -p $P4DPORT'
test_expect_success setup '
mkdir -p "$db" &&
p4d -q -d -r "$db" -p $P4DPORT &&
mkdir -p "$cli" &&
mkdir -p "$git" &&
export P4PORT=localhost:$P4DPORT
'

test_expect_success 'add p4 files' '
cd "$cli" &&
p4 client -i <<-EOF &&
Client: client
Description: client
Root: $cli
View: //depot/... //client/...
EOF
export P4CLIENT=client &&
echo file1 >file1 &&
p4 add file1 &&
p4 submit -d "file1" &&
cd "$TRASH_DIRECTORY"
'

test_expect_success 'basic git-p4 clone' '
"$GITP4" clone --dest="$git" //depot &&
rm -rf "$git" && mkdir "$git"
'

test_expect_success 'exit when p4 fails to produce marshaled output' '
badp4dir="$TRASH_DIRECTORY/badp4dir" &&
mkdir -p "$badp4dir" &&
cat >"$badp4dir"/p4 <<-EOF &&
#!$SHELL_PATH
exit 1
EOF
chmod 755 "$badp4dir"/p4 &&
PATH="$badp4dir:$PATH" "$GITP4" clone --dest="$git" //depot >errs 2>&1 ; retval=$? &&
test $retval -eq 1 &&
test_must_fail grep -q Traceback errs
'

test_expect_success 'add p4 files with wildcards in the names' '
cd "$cli" &&
echo file-wild-hash >file-wild#hash &&
echo file-wild-star >file-wild\*star &&
echo file-wild-at >file-wild@at &&
echo file-wild-percent >file-wild%percent &&
p4 add -f file-wild* &&
p4 submit -d "file wildcards" &&
cd "$TRASH_DIRECTORY"
'

test_expect_success 'wildcard files git-p4 clone' '
"$GITP4" clone --dest="$git" //depot &&
cd "$git" &&
test -f file-wild#hash &&
test -f file-wild\*star &&
test -f file-wild@at &&
test -f file-wild%percent &&
cd "$TRASH_DIRECTORY" &&
rm -rf "$git" && mkdir "$git"
'

test_expect_success 'clone bare' '
"$GITP4" clone --dest="$git" --bare //depot &&
cd "$git" &&
test ! -d .git &&
bare=`git config --get core.bare` &&
test "$bare" = true &&
cd "$TRASH_DIRECTORY" &&
rm -rf "$git" && mkdir "$git"
'

test_expect_success 'shutdown' '
pid=`pgrep -f p4d` &&
test -n "$pid" &&
test_debug "ps wl `echo $pid`" &&
kill $pid
'

test_done
Loading…
Cancel
Save