git-p4: recognize all p4 filetypes

The previous code was approximate in the filetypes it recognized. Put in the canonical list and be more careful about matching elements of the file type. This might change behavior in some cases, hopefully for the better. Windows newline mangling will now happen on all text files. Previously some like "text+ko" were oddly exempt. Files with multiple combinations of modifiers, like "text+klx", are now recognized for keyword expansion. I expect these to be seen only rarely. Acked-by: Luke Diamand <luke@diamand.org> Signed-off-by: Pete Wyckoff <pw@padd.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Pete Wyckoff committed Oct 16, 2011 at 10:45 UTC 9cffb8c8bfd64d97769b3e3792201bcb3618dd23
1 file changed +52 -19
contrib/fast-import/git-p4
+52 -19
@@ -118,13 +118,41 @@ def p4_system(cmd):
118 real_cmd = p4_build_cmd(cmd)
119 return system(real_cmd)
120
121 -def isP4Exec(kind):
122 - """Determine if a Perforce 'kind' should have execute permission
121 +#
122 +# Canonicalize the p4 type and return a tuple of the
123 +# base type, plus any modifiers. See "p4 help filetypes"
124 +# for a list and explanation.
125 +#
126 +def split_p4_type(p4type):
127 +
128 + p4_filetypes_historical = {
129 + "ctempobj": "binary+Sw",
130 + "ctext": "text+C",
131 + "cxtext": "text+Cx",
132 + "ktext": "text+k",
133 + "kxtext": "text+kx",
134 + "ltext": "text+F",
135 + "tempobj": "binary+FSw",
136 + "ubinary": "binary+F",
137 + "uresource": "resource+F",
138 + "uxbinary": "binary+Fx",
139 + "xbinary": "binary+x",
140 + "xltext": "text+Fx",
141 + "xtempobj": "binary+Swx",
142 + "xtext": "text+x",
143 + "xunicode": "unicode+x",
144 + "xutf16": "utf16+x",
145 + }
146 + if p4type in p4_filetypes_historical:
147 + p4type = p4_filetypes_historical[p4type]
148 + mods = ""
149 + s = p4type.split("+")
150 + base = s[0]
151 + mods = ""
152 + if len(s) > 1:
153 + mods = s[1]
154 + return (base, mods)
155
124 - 'p4 help filetypes' gives a list of the types. If it starts with 'x',
125 - or x follows one of a few letters. Otherwise, if there is an 'x' after
126 - a plus sign, it is also executable"""
127 - return (re.search(r"(^[cku]?x)|\+.*x", kind) != None)
156
157 def setP4ExecBit(file, mode):
158 # Reopens an already open file and changes the execute bit to match
@@ -1229,16 +1257,18 @@ class P4Sync(Command, P4UserMap):
1257 if verbose:
1258 sys.stderr.write("%s\n" % relPath)
1259
1232 - mode = "644"
1233 - if isP4Exec(file["type"]):
1234 - mode = "755"
1235 - elif file["type"] == "symlink":
1236 - mode = "120000"
1237 - # p4 print on a symlink contains "target\n", so strip it off
1260 + (type_base, type_mods) = split_p4_type(file["type"])
1261 +
1262 + git_mode = "100644"
1263 + if "x" in type_mods:
1264 + git_mode = "100755"
1265 + if type_base == "symlink":
1266 + git_mode = "120000"
1267 + # p4 print on a symlink contains "target\n"; remove the newline
1268 data = ''.join(contents)
1269 contents = [data[:-1]]
1270
1241 - if file['type'].startswith("utf16"):
1271 + if type_base == "utf16":
1272 # p4 delivers different text in the python output to -G
1273 # than it does when using "print -o", or normal p4 client
1274 # operations. utf16 is converted to ascii or utf8, perhaps.
@@ -1247,7 +1277,9 @@ class P4Sync(Command, P4UserMap):
1277 text = p4_read_pipe('print -q -o - "%s"' % file['depotFile'])
1278 contents = [ text ]
1279
1250 - if self.isWindows and file["type"].endswith("text"):
1280 + # Perhaps windows wants unicode, utf16 newlines translated too;
1281 + # but this is not doing it.
1282 + if self.isWindows and type_base == "text":
1283 mangled = []
1284 for data in contents:
1285 data = data.replace("\r\n", "\n")
@@ -1256,12 +1288,13 @@ class P4Sync(Command, P4UserMap):
1288
1289 # Note that we do not try to de-mangle keywords on utf16 files,
1290 # even though in theory somebody may want that.
1259 - if file['type'] in ('text+ko', 'unicode+ko', 'binary+ko'):
1260 - contents = map(lambda text: re.sub(r'(?i)\$(Id|Header):[^$]*\$',r'$\1$', text), contents)
1261 - elif file['type'] in ('text+k', 'ktext', 'kxtext', 'unicode+k', 'binary+k'):
1262 - contents = map(lambda text: re.sub(r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$\n]*\$',r'$\1$', text), contents)
1291 + if type_base in ("text", "unicode", "binary"):
1292 + if "ko" in type_mods:
1293 + contents = map(lambda text: re.sub(r'(?i)\$(Id|Header):[^$]*\$', r'$\1$', text), contents)
1294 + elif "k" in type_mods:
1295 + contents = map(lambda text: re.sub(r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$\n]*\$', r'$\1$', text), contents)
1296
1264 - self.gitStream.write("M %s inline %s\n" % (mode, relPath))
1297 + self.gitStream.write("M %s inline %s\n" % (git_mode, relPath))
1298
1299 # total length...
1300 length = 0