sapling/eden/scm/tests/generateworkingcopystates.py
Zeyi (Rice) Fan 09d7bb259c make part of the tests Python 3 compatible
Summary:
Most of these tests use `file` instead of `open` for opening files, which is removed in Python 3. And when we open files in byte mode, Python disallows writing `str` into such files, so we add `b` prefix to write actual bytes instead.

There are some other minor problems like reading from `sys.stdin` gives you `str` while expecting `bytes`. The solution is to use `sys.stdin.buffer` instead. However, Python 2 does not have `sys.stdin.buffer` so we have to do a version check to provide compatibility.

Reviewed By: quark-zju

Differential Revision: D19606357

fbshipit-source-id: e9177134294f03af8b581230a57902c3435b319a
2020-01-28 16:42:11 -08:00

110 lines
3.7 KiB
Python

# Helper script used for generating history and working copy files and content.
# The file's name corresponds to its history. The number of changesets can
# be specified on the command line. With 2 changesets, files with names like
# content1_content2_content1-untracked are generated. The first two filename
# segments describe the contents in the two changesets. The third segment
# ("content1-untracked") describes the state in the working copy, i.e.
# the file has content "content1" and is untracked (since it was previously
# tracked, it has been forgotten).
#
# This script generates the filenames and their content, but it's up to the
# caller to tell hg about the state.
#
# There are two subcommands:
# filelist <numchangesets>
# state <numchangesets> (<changeset>|wc)
#
# Typical usage:
#
# $ python $TESTDIR/generateworkingcopystates.py state 2 1
# $ hg addremove --similarity 0
# $ hg commit -m 'first'
#
# $ python $TESTDIR/generateworkingcopystates.py state 2 1
# $ hg addremove --similarity 0
# $ hg commit -m 'second'
#
# $ python $TESTDIR/generateworkingcopystates.py state 2 wc
# $ hg addremove --similarity 0
# $ hg forget *_*_*-untracked
# $ rm *_*_missing-*
from __future__ import absolute_import, print_function
import os
import sys
# Generates pairs of (filename, contents), where 'contents' is a list
# describing the file's content at each revision (or in the working copy).
# At each revision, it is either None or the file's actual content. When not
# None, it may be either new content or the same content as an earlier
# revisions, so all of (modified,clean,added,removed) can be tested.
def generatestates(maxchangesets, parentcontents):
depth = len(parentcontents)
if depth == maxchangesets + 1:
for tracked in ("untracked", "tracked"):
filename = (
"_".join(
[
(content is None and "missing" or content)
for content in parentcontents
]
)
+ "-"
+ tracked
)
yield (filename, parentcontents)
else:
for content in {None, "content" + str(depth + 1)} | set(parentcontents):
for combination in generatestates(
maxchangesets, parentcontents + [content]
):
yield combination
def main(target, maxchangesets, depth=None):
# sort to make sure we have stable output
combinations = sorted(generatestates(maxchangesets, []))
output = []
# compute file content
content = []
for filename, states in combinations:
if target == "filelist":
output.append(filename)
elif target == "state":
if depth == "wc":
# Make sure there is content so the file gets written and can be
# tracked. It will be deleted outside of this script.
content.append((filename, states[maxchangesets] or "TOBEDELETED"))
else:
content.append((filename, states[int(depth) - 1]))
else:
print("unknown target:", target, file=sys.stderr)
raise RuntimeError
# write actual content
for filename, data in content:
if data is not None:
f = open(filename, "wb")
f.write((data + "\n").encode("utf-8"))
f.close()
elif os.path.exists(filename):
os.remove(filename)
return "\n".join(output)
if __name__ == "__main__":
# retrieve the command line arguments
target = sys.argv[1]
maxchangesets = int(sys.argv[2])
if target == "state":
depth = sys.argv[3]
else:
depth = None
output = main(target, maxchangesets, depth)
if output:
print(output)