Browse Source

Merge branch 'pw/p4-update'

* pw/p4-update:
  git-p4: handle files with shell metacharacters
  git-p4: keyword flattening fixes
  git-p4: stop ignoring apple filetype
  git-p4: recognize all p4 filetypes
  git-p4: handle utf16 filetype properly
  git-p4 tests: refactor and cleanup
maint
Junio C Hamano 13 years ago
parent
commit
5a4fcc28e1
  1. 287
      contrib/fast-import/git-p4
  2. 74
      t/lib-git-p4.sh
  3. 576
      t/t9800-git-p4.sh
  4. 233
      t/t9801-git-p4-branch.sh
  5. 108
      t/t9802-git-p4-filetype.sh
  6. 64
      t/t9803-git-shell-metachars.sh

287
contrib/fast-import/git-p4

@ -22,36 +22,39 @@ def p4_build_cmd(cmd):
location. It means that hooking into the environment, or other configuration location. It means that hooking into the environment, or other configuration
can be done more easily. can be done more easily.
""" """
real_cmd = "%s " % "p4" real_cmd = ["p4"]


user = gitConfig("git-p4.user") user = gitConfig("git-p4.user")
if len(user) > 0: if len(user) > 0:
real_cmd += "-u %s " % user real_cmd += ["-u",user]


password = gitConfig("git-p4.password") password = gitConfig("git-p4.password")
if len(password) > 0: if len(password) > 0:
real_cmd += "-P %s " % password real_cmd += ["-P", password]


port = gitConfig("git-p4.port") port = gitConfig("git-p4.port")
if len(port) > 0: if len(port) > 0:
real_cmd += "-p %s " % port real_cmd += ["-p", port]


host = gitConfig("git-p4.host") host = gitConfig("git-p4.host")
if len(host) > 0: if len(host) > 0:
real_cmd += "-h %s " % host real_cmd += ["-h", host]


client = gitConfig("git-p4.client") client = gitConfig("git-p4.client")
if len(client) > 0: if len(client) > 0:
real_cmd += "-c %s " % client real_cmd += ["-c", client]


real_cmd += "%s" % (cmd)
if verbose: if isinstance(cmd,basestring):
print real_cmd real_cmd = ' '.join(real_cmd) + ' ' + cmd
else:
real_cmd += cmd
return real_cmd return real_cmd


def chdir(dir): def chdir(dir):
if os.name == 'nt': # P4 uses the PWD environment variable rather than getcwd(). Since we're
os.environ['PWD']=dir # not using the shell, we have to set it ourselves.
os.environ['PWD']=dir
os.chdir(dir) os.chdir(dir)


def die(msg): def die(msg):
@ -61,29 +64,34 @@ def die(msg):
sys.stderr.write(msg + "\n") sys.stderr.write(msg + "\n")
sys.exit(1) sys.exit(1)


def write_pipe(c, str): def write_pipe(c, stdin):
if verbose: if verbose:
sys.stderr.write('Writing pipe: %s\n' % c) sys.stderr.write('Writing pipe: %s\n' % str(c))


pipe = os.popen(c, 'w') expand = isinstance(c,basestring)
val = pipe.write(str) p = subprocess.Popen(c, stdin=subprocess.PIPE, shell=expand)
if pipe.close(): pipe = p.stdin
die('Command failed: %s' % c) val = pipe.write(stdin)
pipe.close()
if p.wait():
die('Command failed: %s' % str(c))


return val return val


def p4_write_pipe(c, str): def p4_write_pipe(c, stdin):
real_cmd = p4_build_cmd(c) real_cmd = p4_build_cmd(c)
return write_pipe(real_cmd, str) return write_pipe(real_cmd, stdin)


def read_pipe(c, ignore_error=False): def read_pipe(c, ignore_error=False):
if verbose: if verbose:
sys.stderr.write('Reading pipe: %s\n' % c) sys.stderr.write('Reading pipe: %s\n' % str(c))


pipe = os.popen(c, 'rb') expand = isinstance(c,basestring)
p = subprocess.Popen(c, stdout=subprocess.PIPE, shell=expand)
pipe = p.stdout
val = pipe.read() val = pipe.read()
if pipe.close() and not ignore_error: if p.wait() and not ignore_error:
die('Command failed: %s' % c) die('Command failed: %s' % str(c))


return val return val


@ -93,12 +101,14 @@ def p4_read_pipe(c, ignore_error=False):


def read_pipe_lines(c): def read_pipe_lines(c):
if verbose: if verbose:
sys.stderr.write('Reading pipe: %s\n' % c) sys.stderr.write('Reading pipe: %s\n' % str(c))
## todo: check return status
pipe = os.popen(c, 'rb') expand = isinstance(c, basestring)
p = subprocess.Popen(c, stdout=subprocess.PIPE, shell=expand)
pipe = p.stdout
val = pipe.readlines() val = pipe.readlines()
if pipe.close(): if pipe.close() or p.wait():
die('Command failed: %s' % c) die('Command failed: %s' % str(c))


return val return val


@ -108,23 +118,73 @@ def p4_read_pipe_lines(c):
return read_pipe_lines(real_cmd) return read_pipe_lines(real_cmd)


def system(cmd): def system(cmd):
expand = isinstance(cmd,basestring)
if verbose: if verbose:
sys.stderr.write("executing %s\n" % cmd) sys.stderr.write("executing %s\n" % str(cmd))
if os.system(cmd) != 0: subprocess.check_call(cmd, shell=expand)
die("command failed: %s" % cmd)


def p4_system(cmd): def p4_system(cmd):
"""Specifically invoke p4 as the system command. """ """Specifically invoke p4 as the system command. """
real_cmd = p4_build_cmd(cmd) real_cmd = p4_build_cmd(cmd)
return system(real_cmd) expand = isinstance(real_cmd, basestring)
subprocess.check_call(real_cmd, shell=expand)

def p4_integrate(src, dest):
p4_system(["integrate", "-Dt", src, dest])

def p4_sync(path):
p4_system(["sync", path])


def isP4Exec(kind): def p4_add(f):
"""Determine if a Perforce 'kind' should have execute permission p4_system(["add", f])

def p4_delete(f):
p4_system(["delete", f])

def p4_edit(f):
p4_system(["edit", f])

def p4_revert(f):
p4_system(["revert", f])

def p4_reopen(type, file):
p4_system(["reopen", "-t", type, file])

#
# Canonicalize the p4 type and return a tuple of the
# base type, plus any modifiers. See "p4 help filetypes"
# for a list and explanation.
#
def split_p4_type(p4type):

p4_filetypes_historical = {
"ctempobj": "binary+Sw",
"ctext": "text+C",
"cxtext": "text+Cx",
"ktext": "text+k",
"kxtext": "text+kx",
"ltext": "text+F",
"tempobj": "binary+FSw",
"ubinary": "binary+F",
"uresource": "resource+F",
"uxbinary": "binary+Fx",
"xbinary": "binary+x",
"xltext": "text+Fx",
"xtempobj": "binary+Swx",
"xtext": "text+x",
"xunicode": "unicode+x",
"xutf16": "utf16+x",
}
if p4type in p4_filetypes_historical:
p4type = p4_filetypes_historical[p4type]
mods = ""
s = p4type.split("+")
base = s[0]
mods = ""
if len(s) > 1:
mods = s[1]
return (base, mods)


'p4 help filetypes' gives a list of the types. If it starts with 'x',
or x follows one of a few letters. Otherwise, if there is an 'x' after
a plus sign, it is also executable"""
return (re.search(r"(^[cku]?x)|\+.*x", kind) != None)


def setP4ExecBit(file, mode): def setP4ExecBit(file, mode):
# Reopens an already open file and changes the execute bit to match # Reopens an already open file and changes the execute bit to match
@ -139,12 +199,12 @@ def setP4ExecBit(file, mode):
if p4Type[-1] == "+": if p4Type[-1] == "+":
p4Type = p4Type[0:-1] p4Type = p4Type[0:-1]


p4_system("reopen -t %s %s" % (p4Type, file)) p4_reopen(p4Type, file)


def getP4OpenedType(file): def getP4OpenedType(file):
# Returns the perforce file type for the given file. # Returns the perforce file type for the given file.


result = p4_read_pipe("opened %s" % file) result = p4_read_pipe(["opened", file])
match = re.match(".*\((.+)\)\r?$", result) match = re.match(".*\((.+)\)\r?$", result)
if match: if match:
return match.group(1) return match.group(1)
@ -200,9 +260,17 @@ def isModeExecChanged(src_mode, dst_mode):
return isModeExec(src_mode) != isModeExec(dst_mode) return isModeExec(src_mode) != isModeExec(dst_mode)


def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None): def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None):
cmd = p4_build_cmd("-G %s" % (cmd))
if isinstance(cmd,basestring):
cmd = "-G " + cmd
expand = True
else:
cmd = ["-G"] + cmd
expand = False

cmd = p4_build_cmd(cmd)
if verbose: if verbose:
sys.stderr.write("Opening pipe: %s\n" % cmd) sys.stderr.write("Opening pipe: %s\n" % str(cmd))


# Use a temporary file to avoid deadlocks without # Use a temporary file to avoid deadlocks without
# subprocess.communicate(), which would put another copy # subprocess.communicate(), which would put another copy
@ -210,11 +278,16 @@ def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None):
stdin_file = None stdin_file = None
if stdin is not None: if stdin is not None:
stdin_file = tempfile.TemporaryFile(prefix='p4-stdin', mode=stdin_mode) stdin_file = tempfile.TemporaryFile(prefix='p4-stdin', mode=stdin_mode)
stdin_file.write(stdin) if isinstance(stdin,basestring):
stdin_file.write(stdin)
else:
for i in stdin:
stdin_file.write(i + '\n')
stdin_file.flush() stdin_file.flush()
stdin_file.seek(0) stdin_file.seek(0)


p4 = subprocess.Popen(cmd, shell=True, p4 = subprocess.Popen(cmd,
shell=expand,
stdin=stdin_file, stdin=stdin_file,
stdout=subprocess.PIPE) stdout=subprocess.PIPE)


@ -247,7 +320,7 @@ def p4Where(depotPath):
if not depotPath.endswith("/"): if not depotPath.endswith("/"):
depotPath += "/" depotPath += "/"
depotPath = depotPath + "..." depotPath = depotPath + "..."
outputList = p4CmdList("where %s" % depotPath) outputList = p4CmdList(["where", depotPath])
output = None output = None
for entry in outputList: for entry in outputList:
if "depotFile" in entry: if "depotFile" in entry:
@ -449,8 +522,10 @@ def originP4BranchesExist():


def p4ChangesForPaths(depotPaths, changeRange): def p4ChangesForPaths(depotPaths, changeRange):
assert depotPaths assert depotPaths
output = p4_read_pipe_lines("changes " + ' '.join (["%s...%s" % (p, changeRange) cmd = ['changes']
for p in depotPaths])) for p in depotPaths:
cmd += ["%s...%s" % (p, changeRange)]
output = p4_read_pipe_lines(cmd)


changes = {} changes = {}
for line in output: for line in output:
@ -533,7 +608,7 @@ class P4Debug(Command):


def run(self, args): def run(self, args):
j = 0 j = 0
for output in p4CmdList(" ".join(args)): for output in p4CmdList(args):
print 'Element: %d' % j print 'Element: %d' % j
j += 1 j += 1
print output print output
@ -687,7 +762,7 @@ class P4Submit(Command, P4UserMap):
break break
if not client: if not client:
die("could not get client spec") die("could not get client spec")
results = p4CmdList("changes -c %s -m 1" % client) results = p4CmdList(["changes", "-c", client, "-m", "1"])
for r in results: for r in results:
if r.has_key('change'): if r.has_key('change'):
return r['change'] return r['change']
@ -750,7 +825,7 @@ class P4Submit(Command, P4UserMap):
# remove lines in the Files section that show changes to files outside the depot path we're committing into # remove lines in the Files section that show changes to files outside the depot path we're committing into
template = "" template = ""
inFilesSection = False inFilesSection = False
for line in p4_read_pipe_lines("change -o"): for line in p4_read_pipe_lines(['change', '-o']):
if line.endswith("\r\n"): if line.endswith("\r\n"):
line = line[:-2] + "\n" line = line[:-2] + "\n"
if inFilesSection: if inFilesSection:
@ -807,7 +882,7 @@ class P4Submit(Command, P4UserMap):
modifier = diff['status'] modifier = diff['status']
path = diff['src'] path = diff['src']
if modifier == "M": if modifier == "M":
p4_system("edit \"%s\"" % path) p4_edit(path)
if isModeExecChanged(diff['src_mode'], diff['dst_mode']): if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
filesToChangeExecBit[path] = diff['dst_mode'] filesToChangeExecBit[path] = diff['dst_mode']
editedFiles.add(path) editedFiles.add(path)
@ -822,21 +897,21 @@ class P4Submit(Command, P4UserMap):
filesToAdd.remove(path) filesToAdd.remove(path)
elif modifier == "C": elif modifier == "C":
src, dest = diff['src'], diff['dst'] src, dest = diff['src'], diff['dst']
p4_system("integrate -Dt \"%s\" \"%s\"" % (src, dest)) p4_integrate(src, dest)
if diff['src_sha1'] != diff['dst_sha1']: if diff['src_sha1'] != diff['dst_sha1']:
p4_system("edit \"%s\"" % (dest)) p4_edit(dest)
if isModeExecChanged(diff['src_mode'], diff['dst_mode']): if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
p4_system("edit \"%s\"" % (dest)) p4_edit(dest)
filesToChangeExecBit[dest] = diff['dst_mode'] filesToChangeExecBit[dest] = diff['dst_mode']
os.unlink(dest) os.unlink(dest)
editedFiles.add(dest) editedFiles.add(dest)
elif modifier == "R": elif modifier == "R":
src, dest = diff['src'], diff['dst'] src, dest = diff['src'], diff['dst']
p4_system("integrate -Dt \"%s\" \"%s\"" % (src, dest)) p4_integrate(src, dest)
if diff['src_sha1'] != diff['dst_sha1']: if diff['src_sha1'] != diff['dst_sha1']:
p4_system("edit \"%s\"" % (dest)) p4_edit(dest)
if isModeExecChanged(diff['src_mode'], diff['dst_mode']): if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
p4_system("edit \"%s\"" % (dest)) p4_edit(dest)
filesToChangeExecBit[dest] = diff['dst_mode'] filesToChangeExecBit[dest] = diff['dst_mode']
os.unlink(dest) os.unlink(dest)
editedFiles.add(dest) editedFiles.add(dest)
@ -859,9 +934,9 @@ class P4Submit(Command, P4UserMap):
if response == "s": if response == "s":
print "Skipping! Good luck with the next patches..." print "Skipping! Good luck with the next patches..."
for f in editedFiles: for f in editedFiles:
p4_system("revert \"%s\"" % f); p4_revert(f)
for f in filesToAdd: for f in filesToAdd:
system("rm %s" %f) os.remove(f)
return return
elif response == "a": elif response == "a":
os.system(applyPatchCmd) os.system(applyPatchCmd)
@ -882,10 +957,10 @@ class P4Submit(Command, P4UserMap):
system(applyPatchCmd) system(applyPatchCmd)


for f in filesToAdd: for f in filesToAdd:
p4_system("add \"%s\"" % f) p4_add(f)
for f in filesToDelete: for f in filesToDelete:
p4_system("revert \"%s\"" % f) p4_revert(f)
p4_system("delete \"%s\"" % f) p4_delete(f)


# Set/clear executable bits # Set/clear executable bits
for f in filesToChangeExecBit.keys(): for f in filesToChangeExecBit.keys():
@ -907,7 +982,7 @@ class P4Submit(Command, P4UserMap):
del(os.environ["P4DIFF"]) del(os.environ["P4DIFF"])
diff = "" diff = ""
for editedFile in editedFiles: for editedFile in editedFiles:
diff += p4_read_pipe("diff -du %r" % editedFile) diff += p4_read_pipe(['diff', '-du', editedFile])


newdiff = "" newdiff = ""
for newFile in filesToAdd: for newFile in filesToAdd:
@ -959,7 +1034,7 @@ class P4Submit(Command, P4UserMap):
submitTemplate = message[:message.index(separatorLine)] submitTemplate = message[:message.index(separatorLine)]
if self.isWindows: if self.isWindows:
submitTemplate = submitTemplate.replace("\r\n", "\n") submitTemplate = submitTemplate.replace("\r\n", "\n")
p4_write_pipe("submit -i", submitTemplate) p4_write_pipe(['submit', '-i'], submitTemplate)


if self.preserveUser: if self.preserveUser:
if p4User: if p4User:
@ -970,10 +1045,10 @@ class P4Submit(Command, P4UserMap):


else: else:
for f in editedFiles: for f in editedFiles:
p4_system("revert \"%s\"" % f); p4_revert(f)
for f in filesToAdd: for f in filesToAdd:
p4_system("revert \"%s\"" % f); p4_revert(f)
system("rm %s" %f) os.remove(f)


os.remove(fileName) os.remove(fileName)
else: else:
@ -1026,8 +1101,7 @@ class P4Submit(Command, P4UserMap):


chdir(self.clientPath) chdir(self.clientPath)
print "Synchronizing p4 checkout..." print "Synchronizing p4 checkout..."
p4_system("sync ...") p4_sync("...")

self.check() self.check()


commits = [] commits = []
@ -1219,38 +1293,53 @@ class P4Sync(Command, P4UserMap):
# - helper for streamP4Files # - helper for streamP4Files


def streamOneP4File(self, file, contents): def streamOneP4File(self, file, contents):
if file["type"] == "apple":
print "\nfile %s is a strange apple file that forks. Ignoring" % \
file['depotFile']
return

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


mode = "644" (type_base, type_mods) = split_p4_type(file["type"])
if isP4Exec(file["type"]):
mode = "755" git_mode = "100644"
elif file["type"] == "symlink": if "x" in type_mods:
mode = "120000" git_mode = "100755"
# p4 print on a symlink contains "target\n", so strip it off if type_base == "symlink":
git_mode = "120000"
# p4 print on a symlink contains "target\n"; remove the newline
data = ''.join(contents) data = ''.join(contents)
contents = [data[:-1]] contents = [data[:-1]]


if self.isWindows and file["type"].endswith("text"): if type_base == "utf16":
# p4 delivers different text in the python output to -G
# than it does when using "print -o", or normal p4 client
# operations. utf16 is converted to ascii or utf8, perhaps.
# But ascii text saved as -t utf16 is completely mangled.
# Invoke print -o to get the real contents.
text = p4_read_pipe(['print', '-q', '-o', '-', file['depotFile']])
contents = [ text ]

# Perhaps windows wants unicode, utf16 newlines translated too;
# but this is not doing it.
if self.isWindows and type_base == "text":
mangled = [] mangled = []
for data in contents: for data in contents:
data = data.replace("\r\n", "\n") data = data.replace("\r\n", "\n")
mangled.append(data) mangled.append(data)
contents = mangled contents = mangled


if file['type'] in ('text+ko', 'unicode+ko', 'binary+ko'): # Note that we do not try to de-mangle keywords on utf16 files,
contents = map(lambda text: re.sub(r'(?i)\$(Id|Header):[^$]*\$',r'$\1$', text), contents) # even though in theory somebody may want that.
elif file['type'] in ('text+k', 'ktext', 'kxtext', 'unicode+k', 'binary+k'): if type_base in ("text", "unicode", "binary"):
contents = map(lambda text: re.sub(r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$\n]*\$',r'$\1$', text), contents) if "ko" in type_mods:
text = ''.join(contents)
text = re.sub(r'\$(Id|Header):[^$]*\$', r'$\1$', text)
contents = [ text ]
elif "k" in type_mods:
text = ''.join(contents)
text = re.sub(r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$', r'$\1$', text)
contents = [ text ]


self.gitStream.write("M %s inline %s\n" % (mode, relPath)) self.gitStream.write("M %s inline %s\n" % (git_mode, relPath))


# total length... # total length...
length = 0 length = 0
@ -1322,10 +1411,11 @@ class P4Sync(Command, P4UserMap):
def streamP4FilesCbSelf(entry): def streamP4FilesCbSelf(entry):
self.streamP4FilesCb(entry) self.streamP4FilesCb(entry)


p4CmdList("-x - print", fileArgs = ['%s#%s' % (f['path'], f['rev']) for f in filesToRead]
'\n'.join(['%s#%s' % (f['path'], f['rev'])
for f in filesToRead]), p4CmdList(["-x", "-", "print"],
cb=streamP4FilesCbSelf) stdin=fileArgs,
cb=streamP4FilesCbSelf)


# do the last chunk # do the last chunk
if self.stream_file.has_key('depotFile'): if self.stream_file.has_key('depotFile'):
@ -1386,8 +1476,8 @@ class P4Sync(Command, P4UserMap):
if self.verbose: if self.verbose:
print "Change %s is labelled %s" % (change, labelDetails) print "Change %s is labelled %s" % (change, labelDetails)


files = p4CmdList("files " + ' '.join (["%s...@%s" % (p, change) files = p4CmdList(["files"] + ["%s...@%s" % (p, change)
for p in branchPrefixes])) for p in branchPrefixes])


if len(files) == len(labelRevisions): if len(files) == len(labelRevisions):


@ -1435,9 +1525,9 @@ class P4Sync(Command, P4UserMap):
newestChange = 0 newestChange = 0
if self.verbose: if self.verbose:
print "Querying files for label %s" % label print "Querying files for label %s" % label
for file in p4CmdList("files " for file in p4CmdList(["files"] +
+ ' '.join (["%s...@%s" % (p, label) ["%s...@%s" % (p, label)
for p in self.depotPaths])): for p in self.depotPaths]):
revisions[file["depotFile"]] = file["rev"] revisions[file["depotFile"]] = file["rev"]
change = int(file["change"]) change = int(file["change"])
if change > newestChange: if change > newestChange:
@ -1692,10 +1782,9 @@ class P4Sync(Command, P4UserMap):
newestRevision = 0 newestRevision = 0


fileCnt = 0 fileCnt = 0
for info in p4CmdList("files " fileArgs = ["%s...%s" % (p,revision) for p in self.depotPaths]
+ ' '.join(["%s...%s"
% (p, revision) for info in p4CmdList(["files"] + fileArgs):
for p in self.depotPaths])):


if 'code' in info and 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"

74
t/lib-git-p4.sh

@ -0,0 +1,74 @@
#
# Library code for git-p4 tests
#

. ./test-lib.sh

if ! test_have_prereq PYTHON; then
skip_all='skipping git-p4 tests; python not available'
test_done
fi
( 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"

# Try to pick a unique port: guess a large number, then hope
# no more than one of each test is running.
#
# This does not handle the case where somebody else is running the
# same tests and has chosen the same ports.
testid=${this_test#t}
git_p4_test_start=9800
P4DPORT=$((10669 + ($testid - $git_p4_test_start)))

export P4PORT=localhost:$P4DPORT
export P4CLIENT=client

db="$TRASH_DIRECTORY/db"
cli="$TRASH_DIRECTORY/cli"
git="$TRASH_DIRECTORY/git"
pidfile="$TRASH_DIRECTORY/p4d.pid"

start_p4d() {
mkdir -p "$db" "$cli" "$git" &&
(
p4d -q -r "$db" -p $P4DPORT &
echo $! >"$pidfile"
) &&
for i in 1 2 3 4 5 ; do
p4 info >/dev/null 2>&1 && break || true &&
echo waiting for p4d to start &&
sleep 1
done &&
# complain if it never started
p4 info >/dev/null &&
(
cd "$cli" &&
p4 client -i <<-EOF
Client: client
Description: client
Root: $cli
View: //depot/... //client/...
EOF
)
}

kill_p4d() {
pid=$(cat "$pidfile")
# it had better exist for the first kill
kill $pid &&
for i in 1 2 3 4 5 ; do
kill $pid >/dev/null 2>&1 || break
sleep 1
done &&
# complain if it would not die
test_must_fail kill $pid >/dev/null 2>&1 &&
rm -rf "$db" "$cli" "$pidfile"
}

cleanup_git() {
rm -rf "$git"
}

576
t/t9800-git-p4.sh

@ -2,76 +2,51 @@


test_description='git-p4 tests' test_description='git-p4 tests'


. ./test-lib.sh . ./lib-git-p4.sh


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

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

export P4PORT=localhost:$P4DPORT

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


cleanup_git() {
cd "$TRASH_DIRECTORY" &&
rm -rf "$git" &&
mkdir "$git"
}

test_expect_success 'basic git-p4 clone' ' test_expect_success 'basic git-p4 clone' '
"$GITP4" clone --dest="$git" //depot && "$GITP4" clone --dest="$git" //depot &&
test_when_finished cleanup_git && test_when_finished cleanup_git &&
cd "$git" && (
git log --oneline >lines && cd "$git" &&
test_line_count = 1 lines git log --oneline >lines &&
test_line_count = 1 lines
)
' '


test_expect_success 'git-p4 clone @all' ' test_expect_success 'git-p4 clone @all' '
"$GITP4" clone --dest="$git" //depot@all && "$GITP4" clone --dest="$git" //depot@all &&
test_when_finished cleanup_git && test_when_finished cleanup_git &&
cd "$git" && (
git log --oneline >lines && cd "$git" &&
test_line_count = 2 lines git log --oneline >lines &&
test_line_count = 2 lines
)
' '


test_expect_success 'git-p4 sync uninitialized repo' ' test_expect_success 'git-p4 sync uninitialized repo' '
test_create_repo "$git" && test_create_repo "$git" &&
test_when_finished cleanup_git && test_when_finished cleanup_git &&
cd "$git" && (
test_must_fail "$GITP4" sync cd "$git" &&
test_must_fail "$GITP4" sync
)
' '


# #
@ -81,17 +56,19 @@ test_expect_success 'git-p4 sync uninitialized repo' '
test_expect_success 'git-p4 sync new branch' ' test_expect_success 'git-p4 sync new branch' '
test_create_repo "$git" && test_create_repo "$git" &&
test_when_finished cleanup_git && test_when_finished cleanup_git &&
cd "$git" && (
test_commit head && cd "$git" &&
"$GITP4" sync --branch=refs/remotes/p4/depot //depot@all && test_commit head &&
git log --oneline p4/depot >lines && "$GITP4" sync --branch=refs/remotes/p4/depot //depot@all &&
test_line_count = 2 lines git log --oneline p4/depot >lines &&
test_line_count = 2 lines
)
' '


test_expect_success 'exit when p4 fails to produce marshaled output' ' test_expect_success 'exit when p4 fails to produce marshaled output' '
badp4dir="$TRASH_DIRECTORY/badp4dir" && badp4dir="$TRASH_DIRECTORY/badp4dir" &&
mkdir -p "$badp4dir" && mkdir "$badp4dir" &&
test_when_finished "rm -rf $badp4dir" && test_when_finished "rm \"$badp4dir/p4\" && rmdir \"$badp4dir\"" &&
cat >"$badp4dir"/p4 <<-EOF && cat >"$badp4dir"/p4 <<-EOF &&
#!$SHELL_PATH #!$SHELL_PATH
exit 1 exit 1
@ -103,61 +80,61 @@ test_expect_success 'exit when p4 fails to produce marshaled output' '
' '


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


test_expect_success 'wildcard files git-p4 clone' ' test_expect_success 'wildcard files git-p4 clone' '
"$GITP4" clone --dest="$git" //depot && "$GITP4" clone --dest="$git" //depot &&
test_when_finished cleanup_git && test_when_finished cleanup_git &&
cd "$git" && (
test -f file-wild#hash && cd "$git" &&
test -f file-wild\*star && test -f file-wild#hash &&
test -f file-wild@at && test -f file-wild\*star &&
test -f file-wild%percent test -f file-wild@at &&
test -f file-wild%percent
)
' '


test_expect_success 'clone bare' ' test_expect_success 'clone bare' '
"$GITP4" clone --dest="$git" --bare //depot && "$GITP4" clone --dest="$git" --bare //depot &&
test_when_finished cleanup_git && test_when_finished cleanup_git &&
cd "$git" && (
test ! -d .git && cd "$git" &&
bare=`git config --get core.bare` && test ! -d .git &&
test "$bare" = true bare=`git config --get core.bare` &&
test "$bare" = true
)
' '


p4_add_user() { p4_add_user() {
name=$1 name=$1 fullname=$2 &&
fullname=$2 p4 user -f -i <<-EOF &&
p4 user -f -i <<EOF && User: $name
User: $name Email: $name@localhost
Email: $name@localhost FullName: $fullname
FullName: $fullname EOF
EOF p4 passwd -P secret $name
p4 passwd -P secret $name
} }


p4_grant_admin() { p4_grant_admin() {
name=$1 name=$1 &&
p4 protect -o |\ {
awk "{print}END{print \" admin user $name * //depot/...\"}" |\ p4 protect -o &&
p4 protect -i echo " admin user $name * //depot/..."
} | p4 protect -i
} }


p4_check_commit_author() { p4_check_commit_author() {
file=$1 file=$1 user=$2 &&
user=$2 p4 changes -m 1 //depot/$file | grep -q $user
if p4 changes -m 1 //depot/$file | grep $user > /dev/null ; then
return 0
else
echo "file $file not modified by user $user" 1>&2
return 1
fi
} }


make_change_by_user() { make_change_by_user() {
@ -174,15 +151,17 @@ test_expect_success 'preserve users' '
p4_grant_admin alice && p4_grant_admin alice &&
"$GITP4" clone --dest="$git" //depot && "$GITP4" clone --dest="$git" //depot &&
test_when_finished cleanup_git && test_when_finished cleanup_git &&
cd "$git" && (
echo "username: a change by alice" >> file1 && cd "$git" &&
echo "username: a change by bob" >> file2 && echo "username: a change by alice" >>file1 &&
git commit --author "Alice <alice@localhost>" -m "a change by alice" file1 && echo "username: a change by bob" >>file2 &&
git commit --author "Bob <bob@localhost>" -m "a change by bob" file2 && git commit --author "Alice <alice@localhost>" -m "a change by alice" file1 &&
git config git-p4.skipSubmitEditCheck true && git commit --author "Bob <bob@localhost>" -m "a change by bob" file2 &&
P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit --preserve-user && git config git-p4.skipSubmitEditCheck true &&
p4_check_commit_author file1 alice && P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit --preserve-user &&
p4_check_commit_author file2 bob p4_check_commit_author file1 alice &&
p4_check_commit_author file2 bob
)
' '


# Test username support, submitting as bob, who lacks admin rights. Should # Test username support, submitting as bob, who lacks admin rights. Should
@ -190,32 +169,37 @@ test_expect_success 'preserve users' '
test_expect_success 'refuse to preserve users without perms' ' test_expect_success 'refuse to preserve users without perms' '
"$GITP4" clone --dest="$git" //depot && "$GITP4" clone --dest="$git" //depot &&
test_when_finished cleanup_git && test_when_finished cleanup_git &&
cd "$git" && (
git config git-p4.skipSubmitEditCheck true && cd "$git" &&
echo "username-noperms: a change by alice" >> file1 && git config git-p4.skipSubmitEditCheck true &&
git commit --author "Alice <alice@localhost>" -m "perms: a change by alice" file1 && echo "username-noperms: a change by alice" >>file1 &&
! P4EDITOR=touch P4USER=bob P4PASSWD=secret "$GITP4" commit --preserve-user && git commit --author "Alice <alice@localhost>" -m "perms: a change by alice" file1 &&
! git diff --exit-code HEAD..p4/master > /dev/null P4EDITOR=touch P4USER=bob P4PASSWD=secret test_must_fail "$GITP4" commit --preserve-user &&
test_must_fail git diff --exit-code HEAD..p4/master
)
' '


# What happens with unknown author? Without allowMissingP4Users it should fail. # What happens with unknown author? Without allowMissingP4Users it should fail.
test_expect_success 'preserve user where author is unknown to p4' ' test_expect_success 'preserve user where author is unknown to p4' '
"$GITP4" clone --dest="$git" //depot && "$GITP4" clone --dest="$git" //depot &&
test_when_finished cleanup_git && test_when_finished cleanup_git &&
cd "$git" && (
git config git-p4.skipSubmitEditCheck true && cd "$git" &&
echo "username-bob: a change by bob" >> file1 && git config git-p4.skipSubmitEditCheck true &&
git commit --author "Bob <bob@localhost>" -m "preserve: a change by bob" file1 && echo "username-bob: a change by bob" >>file1 &&
echo "username-unknown: a change by charlie" >> file1 && git commit --author "Bob <bob@localhost>" -m "preserve: a change by bob" file1 &&
git commit --author "Charlie <charlie@localhost>" -m "preserve: a change by charlie" file1 && echo "username-unknown: a change by charlie" >>file1 &&
! P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit --preserve-user && git commit --author "Charlie <charlie@localhost>" -m "preserve: a change by charlie" file1 &&
! git diff --exit-code HEAD..p4/master > /dev/null && P4EDITOR=touch P4USER=alice P4PASSWD=secret test_must_fail "$GITP4" commit --preserve-user &&
echo "$0: repeat with allowMissingP4Users enabled" && test_must_fail git diff --exit-code HEAD..p4/master &&
git config git-p4.allowMissingP4Users true &&
git config git-p4.preserveUser true && echo "$0: repeat with allowMissingP4Users enabled" &&
P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit && git config git-p4.allowMissingP4Users true &&
git diff --exit-code HEAD..p4/master > /dev/null && git config git-p4.preserveUser true &&
p4_check_commit_author file1 alice P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit &&
git diff --exit-code HEAD..p4/master &&
p4_check_commit_author file1 alice
)
' '


# If we're *not* using --preserve-user, git-p4 should warn if we're submitting # If we're *not* using --preserve-user, git-p4 should warn if we're submitting
@ -225,33 +209,35 @@ test_expect_success 'preserve user where author is unknown to p4' '
test_expect_success 'not preserving user with mixed authorship' ' test_expect_success 'not preserving user with mixed authorship' '
"$GITP4" clone --dest="$git" //depot && "$GITP4" clone --dest="$git" //depot &&
test_when_finished cleanup_git && test_when_finished cleanup_git &&
cd "$git" && (
git config git-p4.skipSubmitEditCheck true && cd "$git" &&
p4_add_user derek Derek && git config git-p4.skipSubmitEditCheck true &&

p4_add_user derek Derek &&
make_change_by_user usernamefile3 Derek derek@localhost &&
P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >actual && make_change_by_user usernamefile3 Derek derek@localhost &&
grep "git author derek@localhost does not match" actual && P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit |\

grep "git author derek@localhost does not match" &&
make_change_by_user usernamefile3 Charlie charlie@localhost &&
P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >actual && make_change_by_user usernamefile3 Charlie charlie@localhost &&
grep "git author charlie@localhost does not match" actual && P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit |\

grep "git author charlie@localhost does not match" &&
make_change_by_user usernamefile3 alice alice@localhost &&
P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >actual && make_change_by_user usernamefile3 alice alice@localhost &&
! grep "git author.*does not match" actual && P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" |\

test_must_fail grep "git author.*does not match" &&
git config git-p4.skipUserNameCheck true &&
make_change_by_user usernamefile3 Charlie charlie@localhost && git config git-p4.skipUserNameCheck true &&
P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >actual && make_change_by_user usernamefile3 Charlie charlie@localhost &&
! grep "git author.*does not match" actual && P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit |\

test_must_fail grep "git author.*does not match" &&
p4_check_commit_author usernamefile3 alice
p4_check_commit_author usernamefile3 alice
)
' '


marshal_dump() { marshal_dump() {
what=$1 what=$1
python -c 'import marshal, sys; d = marshal.load(sys.stdin); print d["'$what'"]' "$PYTHON_PATH" -c 'import marshal, sys; d = marshal.load(sys.stdin); print d["'$what'"]'
} }


# Sleep a bit so that the top-most p4 change did not happen "now". Then # Sleep a bit so that the top-most p4 change did not happen "now". Then
@ -263,10 +249,12 @@ test_expect_success 'initial import time from top change time' '
sleep 3 && sleep 3 &&
"$GITP4" clone --dest="$git" //depot && "$GITP4" clone --dest="$git" //depot &&
test_when_finished cleanup_git && test_when_finished cleanup_git &&
cd "$git" && (
gittime=$(git show -s --raw --pretty=format:%at HEAD) && cd "$git" &&
echo $p4time $gittime && gittime=$(git show -s --raw --pretty=format:%at HEAD) &&
test $p4time = $gittime echo $p4time $gittime &&
test $p4time = $gittime
)
' '


# Rename a file and confirm that rename is not detected in P4. # Rename a file and confirm that rename is not detected in P4.
@ -279,47 +267,49 @@ test_expect_success 'initial import time from top change time' '
test_expect_success 'detect renames' ' test_expect_success 'detect renames' '
"$GITP4" clone --dest="$git" //depot@all && "$GITP4" clone --dest="$git" //depot@all &&
test_when_finished cleanup_git && test_when_finished cleanup_git &&
cd "$git" && (
git config git-p4.skipSubmitEditCheck true && cd "$git" &&

git config git-p4.skipSubmitEditCheck true &&
git mv file1 file4 &&
git commit -a -m "Rename file1 to file4" && git mv file1 file4 &&
git diff-tree -r -M HEAD && git commit -a -m "Rename file1 to file4" &&
"$GITP4" submit && git diff-tree -r -M HEAD &&
p4 filelog //depot/file4 && "$GITP4" submit &&
! p4 filelog //depot/file4 | grep -q "branch from" && p4 filelog //depot/file4 &&

p4 filelog //depot/file4 | test_must_fail grep -q "branch from" &&
git mv file4 file5 &&
git commit -a -m "Rename file4 to file5" && git mv file4 file5 &&
git diff-tree -r -M HEAD && git commit -a -m "Rename file4 to file5" &&
git config git-p4.detectRenames true && git diff-tree -r -M HEAD &&
"$GITP4" submit && git config git-p4.detectRenames true &&
p4 filelog //depot/file5 && "$GITP4" submit &&
p4 filelog //depot/file5 | grep -q "branch from //depot/file4" && p4 filelog //depot/file5 &&

p4 filelog //depot/file5 | grep -q "branch from //depot/file4" &&
git mv file5 file6 &&
echo update >>file6 && git mv file5 file6 &&
git add file6 && echo update >>file6 &&
git commit -a -m "Rename file5 to file6 with changes" && git add file6 &&
git diff-tree -r -M HEAD && git commit -a -m "Rename file5 to file6 with changes" &&
level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") && git diff-tree -r -M HEAD &&
test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 && level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") &&
git config git-p4.detectRenames $((level + 2)) && test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 &&
"$GITP4" submit && git config git-p4.detectRenames $(($level + 2)) &&
p4 filelog //depot/file6 && "$GITP4" submit &&
! p4 filelog //depot/file6 | grep -q "branch from" && p4 filelog //depot/file6 &&

p4 filelog //depot/file6 | test_must_fail grep -q "branch from" &&
git mv file6 file7 &&
echo update >>file7 && git mv file6 file7 &&
git add file7 && echo update >>file7 &&
git commit -a -m "Rename file6 to file7 with changes" && git add file7 &&
git diff-tree -r -M HEAD && git commit -a -m "Rename file6 to file7 with changes" &&
level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") && git diff-tree -r -M HEAD &&
test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 && level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") &&
git config git-p4.detectRenames $((level - 2)) && test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 &&
"$GITP4" submit && git config git-p4.detectRenames $(($level - 2)) &&
p4 filelog //depot/file7 && "$GITP4" submit &&
p4 filelog //depot/file7 | grep -q "branch from //depot/file6" p4 filelog //depot/file7 &&
p4 filelog //depot/file7 | grep -q "branch from //depot/file6"
)
' '


# Copy a file and confirm that copy is not detected in P4. # Copy a file and confirm that copy is not detected in P4.
@ -336,141 +326,79 @@ test_expect_success 'detect renames' '
test_expect_success 'detect copies' ' test_expect_success 'detect copies' '
"$GITP4" clone --dest="$git" //depot@all && "$GITP4" clone --dest="$git" //depot@all &&
test_when_finished cleanup_git && test_when_finished cleanup_git &&
cd "$git" && (
git config git-p4.skipSubmitEditCheck true && cd "$git" &&

git config git-p4.skipSubmitEditCheck true &&
cp file2 file8 &&
git add file8 && cp file2 file8 &&
git commit -a -m "Copy file2 to file8" && git add file8 &&
git diff-tree -r -C HEAD && git commit -a -m "Copy file2 to file8" &&
"$GITP4" submit && git diff-tree -r -C HEAD &&
p4 filelog //depot/file8 && "$GITP4" submit &&
! p4 filelog //depot/file8 | grep -q "branch from" && p4 filelog //depot/file8 &&

p4 filelog //depot/file8 | test_must_fail grep -q "branch from" &&
cp file2 file9 &&
git add file9 && cp file2 file9 &&
git commit -a -m "Copy file2 to file9" && git add file9 &&
git diff-tree -r -C HEAD && git commit -a -m "Copy file2 to file9" &&
git config git-p4.detectCopies true && git diff-tree -r -C HEAD &&
"$GITP4" submit && git config git-p4.detectCopies true &&
p4 filelog //depot/file9 && "$GITP4" submit &&
! p4 filelog //depot/file9 | grep -q "branch from" && p4 filelog //depot/file9 &&

p4 filelog //depot/file9 | test_must_fail grep -q "branch from" &&
echo "file2" >>file2 &&
cp file2 file10 && echo "file2" >>file2 &&
git add file2 file10 && cp file2 file10 &&
git commit -a -m "Modify and copy file2 to file10" && git add file2 file10 &&
git diff-tree -r -C HEAD && git commit -a -m "Modify and copy file2 to file10" &&
"$GITP4" submit && git diff-tree -r -C HEAD &&
p4 filelog //depot/file10 && "$GITP4" submit &&
p4 filelog //depot/file10 | grep -q "branch from //depot/file" && p4 filelog //depot/file10 &&

p4 filelog //depot/file10 | grep -q "branch from //depot/file" &&
cp file2 file11 &&
git add file11 && cp file2 file11 &&
git commit -a -m "Copy file2 to file11" && git add file11 &&
git diff-tree -r -C --find-copies-harder HEAD && git commit -a -m "Copy file2 to file11" &&
src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && git diff-tree -r -C --find-copies-harder HEAD &&
test "$src" = file10 && src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
git config git-p4.detectCopiesHarder true && test "$src" = file10 &&
"$GITP4" submit && git config git-p4.detectCopiesHarder true &&
p4 filelog //depot/file11 && "$GITP4" submit &&
p4 filelog //depot/file11 | grep -q "branch from //depot/file" && p4 filelog //depot/file11 &&

p4 filelog //depot/file11 | grep -q "branch from //depot/file" &&
cp file2 file12 &&
echo "some text" >>file12 && cp file2 file12 &&
git add file12 && echo "some text" >>file12 &&
git commit -a -m "Copy file2 to file12 with changes" && git add file12 &&
git diff-tree -r -C --find-copies-harder HEAD && git commit -a -m "Copy file2 to file12 with changes" &&
level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") && git diff-tree -r -C --find-copies-harder HEAD &&
test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 && level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") &&
src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 &&
test "$src" = file10 && src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
git config git-p4.detectCopies $((level + 2)) && test "$src" = file10 &&
"$GITP4" submit && git config git-p4.detectCopies $(($level + 2)) &&
p4 filelog //depot/file12 && "$GITP4" submit &&
! p4 filelog //depot/file12 | grep -q "branch from" && p4 filelog //depot/file12 &&

p4 filelog //depot/file12 | test_must_fail grep -q "branch from" &&
cp file2 file13 &&
echo "different text" >>file13 && cp file2 file13 &&
git add file13 && echo "different text" >>file13 &&
git commit -a -m "Copy file2 to file13 with changes" && git add file13 &&
git diff-tree -r -C --find-copies-harder HEAD && git commit -a -m "Copy file2 to file13 with changes" &&
level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") && git diff-tree -r -C --find-copies-harder HEAD &&
test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 && level=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/C0*//") &&
src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) && test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 &&
test "$src" = file10 && src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
git config git-p4.detectCopies $((level - 2)) && test "$src" = file10 &&
"$GITP4" submit && git config git-p4.detectCopies $(($level - 2)) &&
p4 filelog //depot/file13 && "$GITP4" submit &&
p4 filelog //depot/file13 | grep -q "branch from //depot/file" p4 filelog //depot/file13 &&
' p4 filelog //depot/file13 | grep -q "branch from //depot/file"

)
# Create a simple branch structure in P4 depot to check if it is correctly
# cloned.
test_expect_success 'add simple p4 branches' '
cd "$cli" &&
mkdir branch1 &&
cd branch1 &&
echo file1 >file1 &&
echo file2 >file2 &&
p4 add file1 file2 &&
p4 submit -d "branch1" &&
p4 integrate //depot/branch1/... //depot/branch2/... &&
p4 submit -d "branch2" &&
echo file3 >file3 &&
p4 add file3 &&
p4 submit -d "add file3 in branch1" &&
p4 open file2 &&
echo update >>file2 &&
p4 submit -d "update file2 in branch1" &&
p4 integrate //depot/branch1/... //depot/branch3/... &&
p4 submit -d "branch3" &&
cd "$TRASH_DIRECTORY"
'

# Configure branches through git-config and clone them.
# All files are tested to make sure branches were cloned correctly.
# Finally, make an update to branch1 on P4 side to check if it is imported
# correctly by git-p4.
test_expect_success 'git-p4 clone simple branches' '
test_when_finished cleanup_git &&
test_create_repo "$git" &&
cd "$git" &&
git config git-p4.branchList branch1:branch2 &&
git config --add git-p4.branchList branch1:branch3 &&
"$GITP4" clone --dest=. --detect-branches //depot@all &&
git log --all --graph --decorate --stat &&
git reset --hard p4/depot/branch1 &&
test -f file1 &&
test -f file2 &&
test -f file3 &&
grep -q update file2 &&
git reset --hard p4/depot/branch2 &&
test -f file1 &&
test -f file2 &&
test ! -f file3 &&
! grep -q update file2 &&
git reset --hard p4/depot/branch3 &&
test -f file1 &&
test -f file2 &&
test -f file3 &&
grep -q update file2 &&
cd "$cli" &&
cd branch1 &&
p4 edit file2 &&
echo file2_ >>file2 &&
p4 submit -d "update file2 in branch1" &&
cd "$git" &&
git reset --hard p4/depot/branch1 &&
"$GITP4" rebase &&
grep -q file2_ file2
' '


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


test_done test_done

233
t/t9801-git-p4-branch.sh

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

test_description='git-p4 p4 branching tests'

. ./lib-git-p4.sh

test_expect_success 'start p4d' '
start_p4d
'

#
# 1: //depot/main/f1
# 2: //depot/main/f2
# 3: integrate //depot/main/... -> //depot/branch1/...
# 4: //depot/main/f4
# 5: //depot/branch1/f5
# .: named branch branch2
# 6: integrate -b branch2
# 7: //depot/branch2/f7
# 8: //depot/main/f8
#
test_expect_success 'basic p4 branches' '
(
cd "$cli" &&
mkdir -p main &&

echo f1 >main/f1 &&
p4 add main/f1 &&
p4 submit -d "main/f1" &&

echo f2 >main/f2 &&
p4 add main/f2 &&
p4 submit -d "main/f2" &&

p4 integrate //depot/main/... //depot/branch1/... &&
p4 submit -d "integrate main to branch1" &&

echo f4 >main/f4 &&
p4 add main/f4 &&
p4 submit -d "main/f4" &&

echo f5 >branch1/f5 &&
p4 add branch1/f5 &&
p4 submit -d "branch1/f5" &&

p4 branch -i <<-EOF &&
Branch: branch2
View: //depot/main/... //depot/branch2/...
EOF

p4 integrate -b branch2 &&
p4 submit -d "integrate main to branch2" &&

echo f7 >branch2/f7 &&
p4 add branch2/f7 &&
p4 submit -d "branch2/f7" &&

echo f8 >main/f8 &&
p4 add main/f8 &&
p4 submit -d "main/f8"
)
'

test_expect_success 'import main, no branch detection' '
test_when_finished cleanup_git &&
"$GITP4" clone --dest="$git" //depot/main@all &&
(
cd "$git" &&
git log --oneline --graph --decorate --all &&
git rev-list master >wc &&
test_line_count = 4 wc
)
'

test_expect_success 'import branch1, no branch detection' '
test_when_finished cleanup_git &&
"$GITP4" clone --dest="$git" //depot/branch1@all &&
(
cd "$git" &&
git log --oneline --graph --decorate --all &&
git rev-list master >wc &&
test_line_count = 2 wc
)
'

test_expect_success 'import branch2, no branch detection' '
test_when_finished cleanup_git &&
"$GITP4" clone --dest="$git" //depot/branch2@all &&
(
cd "$git" &&
git log --oneline --graph --decorate --all &&
git rev-list master >wc &&
test_line_count = 2 wc
)
'

test_expect_success 'import depot, no branch detection' '
test_when_finished cleanup_git &&
"$GITP4" clone --dest="$git" //depot@all &&
(
cd "$git" &&
git log --oneline --graph --decorate --all &&
git rev-list master >wc &&
test_line_count = 8 wc
)
'

test_expect_success 'import depot, branch detection' '
test_when_finished cleanup_git &&
"$GITP4" clone --dest="$git" --detect-branches //depot@all &&
(
cd "$git" &&

git log --oneline --graph --decorate --all &&

# 4 main commits
git rev-list master >wc &&
test_line_count = 4 wc &&

# 3 main, 1 integrate, 1 on branch2
git rev-list p4/depot/branch2 >wc &&
test_line_count = 5 wc &&

# no branch1, since no p4 branch created for it
test_must_fail git show-ref p4/depot/branch1
)
'

test_expect_success 'import depot, branch detection, branchList branch definition' '
test_when_finished cleanup_git &&
test_create_repo "$git" &&
(
cd "$git" &&
git config git-p4.branchList main:branch1 &&
"$GITP4" clone --dest=. --detect-branches //depot@all &&

git log --oneline --graph --decorate --all &&

# 4 main commits
git rev-list master >wc &&
test_line_count = 4 wc &&

# 3 main, 1 integrate, 1 on branch2
git rev-list p4/depot/branch2 >wc &&
test_line_count = 5 wc &&

# 2 main, 1 integrate, 1 on branch1
git rev-list p4/depot/branch1 >wc &&
test_line_count = 4 wc
)
'

test_expect_success 'restart p4d' '
kill_p4d &&
start_p4d
'

#
# 1: //depot/branch1/file1
# //depot/branch1/file2
# 2: integrate //depot/branch1/... -> //depot/branch2/...
# 3: //depot/branch1/file3
# 4: //depot/branch1/file2 (edit)
# 5: integrate //depot/branch1/... -> //depot/branch3/...
#
## Create a simple branch structure in P4 depot.
test_expect_success 'add simple p4 branches' '
(
cd "$cli" &&
mkdir branch1 &&
cd branch1 &&
echo file1 >file1 &&
echo file2 >file2 &&
p4 add file1 file2 &&
p4 submit -d "branch1" &&
p4 integrate //depot/branch1/... //depot/branch2/... &&
p4 submit -d "branch2" &&
echo file3 >file3 &&
p4 add file3 &&
p4 submit -d "add file3 in branch1" &&
p4 open file2 &&
echo update >>file2 &&
p4 submit -d "update file2 in branch1" &&
p4 integrate //depot/branch1/... //depot/branch3/... &&
p4 submit -d "branch3"
)
'

# Configure branches through git-config and clone them.
# All files are tested to make sure branches were cloned correctly.
# Finally, make an update to branch1 on P4 side to check if it is imported
# correctly by git-p4.
test_expect_success 'git-p4 clone simple branches' '
test_when_finished cleanup_git &&
test_create_repo "$git" &&
(
cd "$git" &&
git config git-p4.branchList branch1:branch2 &&
git config --add git-p4.branchList branch1:branch3 &&
"$GITP4" clone --dest=. --detect-branches //depot@all &&
git log --all --graph --decorate --stat &&
git reset --hard p4/depot/branch1 &&
test -f file1 &&
test -f file2 &&
test -f file3 &&
grep -q update file2 &&
git reset --hard p4/depot/branch2 &&
test -f file1 &&
test -f file2 &&
test ! -f file3 &&
test_must_fail grep -q update file2 &&
git reset --hard p4/depot/branch3 &&
test -f file1 &&
test -f file2 &&
test -f file3 &&
grep -q update file2 &&
cd "$cli" &&
cd branch1 &&
p4 edit file2 &&
echo file2_ >>file2 &&
p4 submit -d "update file2 in branch3" &&
cd "$git" &&
git reset --hard p4/depot/branch1 &&
"$GITP4" rebase &&
grep -q file2_ file2
)
'

test_expect_success 'kill p4d' '
kill_p4d
'

test_done

108
t/t9802-git-p4-filetype.sh

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

test_description='git-p4 p4 filetype tests'

. ./lib-git-p4.sh

test_expect_success 'start p4d' '
start_p4d
'

test_expect_success 'utf-16 file create' '
(
cd "$cli" &&

# p4 saves this verbatim
printf "three\nline\ntext\n" >f-ascii &&
p4 add -t text f-ascii &&

# p4 adds \377\376 header
cp f-ascii f-ascii-as-utf16 &&
p4 add -t utf16 f-ascii-as-utf16 &&

# p4 saves this exactly as iconv produced it
printf "three\nline\ntext\n" | iconv -f ascii -t utf-16 >f-utf16 &&
p4 add -t utf16 f-utf16 &&

# this also is unchanged
cp f-utf16 f-utf16-as-text &&
p4 add -t text f-utf16-as-text &&

p4 submit -d "f files" &&

# force update of client files
p4 sync -f
)
'

test_expect_success 'utf-16 file test' '
test_when_finished cleanup_git &&
"$GITP4" clone --dest="$git" //depot@all &&
(
cd "$git" &&

test_cmp "$cli/f-ascii" f-ascii &&
test_cmp "$cli/f-ascii-as-utf16" f-ascii-as-utf16 &&
test_cmp "$cli/f-utf16" f-utf16 &&
test_cmp "$cli/f-utf16-as-text" f-utf16-as-text
)
'

test_expect_success 'keyword file create' '
(
cd "$cli" &&

printf "id\n\$Id\$\n\$Author\$\ntext\n" >k-text-k &&
p4 add -t text+k k-text-k &&

cp k-text-k k-text-ko &&
p4 add -t text+ko k-text-ko &&

cat k-text-k | iconv -f ascii -t utf-16 >k-utf16-k &&
p4 add -t utf16+k k-utf16-k &&

cp k-utf16-k k-utf16-ko &&
p4 add -t utf16+ko k-utf16-ko &&

p4 submit -d "k files" &&
p4 sync -f
)
'

build_smush() {
cat >k_smush.py <<-\EOF &&
import re, sys
sys.stdout.write(re.sub(r'(?i)\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$', r'$\1$', sys.stdin.read()))
EOF
cat >ko_smush.py <<-\EOF
import re, sys
sys.stdout.write(re.sub(r'(?i)\$(Id|Header):[^$]*\$', r'$\1$', sys.stdin.read()))
EOF
}

test_expect_success 'keyword file test' '
build_smush &&
test_when_finished rm -f k_smush.py ko_smush.py &&
test_when_finished cleanup_git &&
"$GITP4" clone --dest="$git" //depot@all &&
(
cd "$git" &&

# text, ensure unexpanded
"$PYTHON_PATH" "$TRASH_DIRECTORY/k_smush.py" <"$cli/k-text-k" >cli-k-text-k-smush &&
test_cmp cli-k-text-k-smush k-text-k &&
"$PYTHON_PATH" "$TRASH_DIRECTORY/ko_smush.py" <"$cli/k-text-ko" >cli-k-text-ko-smush &&
test_cmp cli-k-text-ko-smush k-text-ko &&

# utf16, even though p4 expands keywords, git-p4 does not
# try to undo that
test_cmp "$cli/k-utf16-k" k-utf16-k &&
test_cmp "$cli/k-utf16-ko" k-utf16-ko
)
'

test_expect_success 'kill p4d' '
kill_p4d
'

test_done

64
t/t9803-git-shell-metachars.sh

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

test_description='git-p4 transparency to shell metachars in filenames'

. ./lib-git-p4.sh

test_expect_success 'start p4d' '
start_p4d
'

test_expect_success 'init depot' '
(
cd "$cli" &&
echo file1 >file1 &&
p4 add file1 &&
p4 submit -d "file1"
)
'

test_expect_success 'shell metachars in filenames' '
"$GITP4" clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
git config git-p4.skipSubmitEditCheck true &&
echo f1 >foo\$bar &&
git add foo\$bar &&
echo f2 >"file with spaces" &&
git add "file with spaces" &&
git commit -m "add files" &&
P4EDITOR=touch "$GITP4" submit
) &&
(
cd "$cli" &&
p4 sync ... &&
test -e "file with spaces" &&
test -e "foo\$bar"
)
'

test_expect_success 'deleting with shell metachars' '
"$GITP4" clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
git config git-p4.skipSubmitEditCheck true &&
git rm foo\$bar &&
git rm file\ with\ spaces &&
git commit -m "remove files" &&
P4EDITOR=touch "$GITP4" submit
) &&
(
cd "$cli" &&
p4 sync ... &&
test ! -e "file with spaces" &&
test ! -e foo\$bar
)
'

test_expect_success 'kill p4d' '
kill_p4d
'

test_done
Loading…
Cancel
Save