Skip to content

Commit b3d41e7

Browse files
authored
Allow stream-switching when re-using a client on new host (#189)
1 parent 12dcab4 commit b3d41e7

File tree

3 files changed

+55
-5
lines changed

3 files changed

+55
-5
lines changed

python/fixture/server.zip

3.66 KB
Binary file not shown.

python/perforce.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,22 @@ def insert_clientname(mapping):
7777
return '%s //%s/%s' % (depot, clientname, local)
7878
return [insert_clientname(mapping) for mapping in view]
7979

80+
def _flush_to_previous_client(self, current_client, prev_clientname):
81+
"""Flush a new client to match existing workspace data from a previous client"""
82+
prev_client = self.perforce.fetch_client(prev_clientname)
83+
stream_switch = self.stream and prev_client._stream != self.stream
84+
if stream_switch:
85+
self.perforce.logger.info("previous client stream %s does not match %s, switching stream temporarily to flush" % (prev_client._stream, self.stream))
86+
current_client._stream = prev_client._stream
87+
self.perforce.save_client(current_client)
88+
89+
self.perforce.run_flush(['//...@%s' % prev_clientname])
90+
91+
if stream_switch:
92+
self.perforce.logger.info("switching stream back to %s" % self.stream)
93+
current_client._stream = self.stream
94+
self.perforce.save_client(current_client)
95+
8096
def _setup_client(self):
8197
"""Creates or re-uses the client workspace for this machine"""
8298
# pylint: disable=protected-access
@@ -107,7 +123,8 @@ def _setup_client(self):
107123
if line.startswith('P4CLIENT='))
108124
if prev_clientname != clientname:
109125
self.perforce.logger.warning("p4config last client was %s, flushing workspace to match" % prev_clientname)
110-
self.perforce.run_flush(['//...@%s' % prev_clientname])
126+
self._flush_to_previous_client(client, prev_clientname)
127+
111128
elif 'Update' in client: # client was accessed previously
112129
self.perforce.logger.warning("p4config missing for previously accessed client workspace. flushing to revision zero")
113130
self.perforce.run_flush(['//...@0'])

python/test_perforce.py

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ def test_fixture(capsys, server):
106106
assert depotfile_to_content == {
107107
"//depot/file.txt": "Hello World\n",
108108
"//stream-depot/main/file.txt": "Hello Stream World\n",
109+
"//stream-depot/main/file_2.txt": "file_2\n",
109110
"//stream-depot/dev/file.txt": "Hello Stream World (dev)\n",
110111
}
111112

@@ -143,6 +144,11 @@ def test_fixture(capsys, server):
143144
'action': ['edit'],
144145
'depotFile': ['//stream-depot/dev/file.txt'],
145146
'desc': 'Update contents of //stream-depot/dev/file.txt\n'
147+
},
148+
'9': {
149+
'action': ['add'],
150+
'depotFile': ['//stream-depot/main/file_2.txt'],
151+
'desc': 'file_2.txt - exists in main but not dev\n'
146152
}
147153
}
148154

@@ -188,11 +194,12 @@ def test_fixture(capsys, server):
188194

189195
def test_head(server, tmpdir):
190196
"""Test resolve of HEAD changelist"""
191-
repo = P4Repo(root=tmpdir)
192-
assert repo.head() == "@6", "Unexpected global HEAD revision"
197+
# workspace with no changes in view defaults to global view
198+
repo = P4Repo(root=tmpdir, view="//depot/empty_dir/... empty_dir/...")
199+
assert repo.head() == "@9", "Unexpected global HEAD revision"
193200

194-
repo = P4Repo(root=tmpdir, stream='//stream-depot/main')
195-
assert repo.head() == "@2", "Unexpected HEAD revision for stream"
201+
repo = P4Repo(root=tmpdir, stream='//stream-depot/dev')
202+
assert repo.head() == "@8", "Unexpected HEAD revision for stream"
196203

197204
repo = P4Repo(root=tmpdir, stream='//stream-depot/idontexist')
198205
with pytest.raises(Exception, match=r"Stream '//stream-depot/idontexist' doesn't exist."):
@@ -413,16 +420,42 @@ def test_stream_switching(server, tmpdir):
413420
repo = P4Repo(root=tmpdir, stream='//stream-depot/main')
414421
synced = repo.sync()
415422
assert len(synced) > 0, "Didn't sync any files"
423+
assert set(os.listdir(tmpdir)) == set([
424+
"file.txt", "file_2.txt", "p4config"])
416425
with open(os.path.join(tmpdir, "file.txt")) as content:
417426
assert content.read() == "Hello Stream World\n", "Unexpected content in workspace file"
418427

419428
# Re-use the same checkout directory, but switch streams
420429
repo = P4Repo(root=tmpdir, stream='//stream-depot/dev')
421430
repo.sync()
422431
assert len(synced) > 0, "Didn't sync any files"
432+
assert set(os.listdir(tmpdir)) == set([
433+
"file.txt", "p4config"]) # file_2.txt was de-synced
423434
with open(os.path.join(tmpdir, "file.txt")) as content:
424435
assert content.read() == "Hello Stream World (dev)\n", "Unexpected content in workspace file"
425436

437+
def test_stream_switching_migration(server, tmpdir):
438+
"""Test stream-switching and client migration simultaneously"""
439+
repo = P4Repo(root=tmpdir, stream='//stream-depot/main')
440+
synced = repo.sync()
441+
assert len(synced) > 0, "Didn't sync any files"
442+
assert set(os.listdir(tmpdir)) == set([
443+
"file.txt", "file_2.txt", "p4config"])
444+
with open(os.path.join(tmpdir, "file.txt")) as content:
445+
assert content.read() == "Hello Stream World\n", "Unexpected content in workspace file"
446+
447+
with tempfile.TemporaryDirectory(prefix="bk-p4-test-") as second_client:
448+
copytree(tmpdir, second_client)
449+
# Client names include path on disk, so this creates a new unique client
450+
# Re-use the same checkout directory and switch streams at the same time
451+
repo = P4Repo(root=second_client, stream='//stream-depot/dev')
452+
repo.sync()
453+
assert len(synced) > 0, "Didn't sync any files"
454+
assert set(os.listdir(second_client)) == set([
455+
"file.txt", "p4config"]) # file_2.txt was de-synced
456+
with open(os.path.join(second_client, "file.txt")) as content:
457+
assert content.read() == "Hello Stream World (dev)\n", "Unexpected content in workspace file"
458+
426459

427460
# def test_live_server():
428461
# """Reproduce production issues quickly by writing tests which run against a real server"""

0 commit comments

Comments
 (0)