seqimport - make it survive CLs that have moves outside of clientspec

Summary:
seqimport currently has a gap: if a changelist touches files outside of
clientspec, it will blow up when trying to get the move info for it. Even if that
was not the case, it could blow up if the file was moved into the clientspec.

This change makes it resilient to that by providing the same list created by
`parse_fstat` to prefilter files we check for move info, and then making
`parse_where` take an optional parameter saying it is fine if file is not on
client (i.e. moved into clientspec)

Differential Revision: D7574415

fbshipit-source-id: 63f6a32436d3d53d6f9402575a9a13bb4187b76c
This commit is contained in:
Alexandre Marin 2018-04-10 15:19:42 -07:00 committed by Saurabh Singh
parent 5346a46bb5
commit 1fde98d0db
2 changed files with 27 additions and 7 deletions

View File

@ -26,10 +26,14 @@ KEYWORD_REGEX = "\$(Id|Header|DateTime|" + \
#TODO: make p4 user configurable
P4_ADMIN_USER = 'p4admin'
def relpath(client, depotfile):
def relpath(client, depotfile, ignore_nonexisting=False):
where = p4.parse_where(client, depotfile)
filename = where['clientFile'].replace('//%s/' % client, '')
return p4.decodefilename(filename)
filename = where.get('clientFile')
if filename is not None:
filename = filename.replace('//%s/' % client, '')
elif not ignore_nonexisting:
raise error.Abort('Could not find file %s' % (depotfile))
return p4.decodefilename(filename) if filename is not None else filename
def get_localname(client, p4filelogs):
for p4fl in p4filelogs:

View File

@ -47,7 +47,7 @@ class ChangelistImporter(object):
else:
added_or_modified.append((p4path, hgpath))
moved = self._get_move_info(p4cl)
moved = self._get_move_info(p4cl, p4flogs)
node = self._create_commit(p4cl, p4flogs, removed, moved)
largefiles = self._get_largefiles(p4cl, added_or_modified, node)
@ -65,14 +65,30 @@ class ChangelistImporter(object):
self.ui.debug('largefile: %s, oid: %s\n' % (hgpath, oid))
return largefiles
def _get_move_info(self, p4cl):
def _get_move_info(self, p4cl, p4flogs):
'''Returns a dict where entries are (dst, src)'''
moves = {}
files_in_clientspec = {
p4flog._depotfile: hgpath for hgpath, p4flog in p4flogs.items()
}
for filename, info in p4cl.parsed['files'].items():
if filename not in files_in_clientspec:
continue
src = info.get('src')
if src:
hgsrc = importer.relpath(self.client, src)
hgdst = importer.relpath(self.client, filename)
hgdst = files_in_clientspec[filename]
# The below could return None if the source of the move is
# outside of client view. That is expected.
# This info will be used when creating the commit, and value of
# None in the moves dictionary is a no-op, it will treat it as
# an add in hg. As it just came into the client view we cannot
# store any move info for it in hg (even though it was a legit
# move in perforce).
hgsrc = importer.relpath(
self.client,
src,
ignore_nonexisting=True,
)
moves[hgdst] = hgsrc
return moves