def svn_delete(self, rpath, even_if_modified=False): "Delete a WC path locally." lpath = local_path(rpath) args = [] if even_if_modified: args += ['--force'] actions.run_and_verify_svn(None, None, [], 'delete', lpath, *args)
def fail_add_mixed_eol_style(sbox): "fail to add a file with mixed EOL style" from svntest.actions import run_and_verify_svn, run_and_verify_unquiet_status # Bootstrap sbox.build() filename = 'mixed-eol.txt' filepath = os.path.join(sbox.wc_dir, filename) parameters = [ '--auto-props', '--config-option=config:auto-props:' + filename + '=svn:eol-style=native' ] svntest.main.file_write(filepath, 'foo\nbar\r\nbaz\r') expected_stderr = "svn: E200009: File '.*" + filename + \ "' has inconsistent newlines" + \ "|" + "svn: E135000: Inconsistent line ending style\n" run_and_verify_svn(None, [], expected_stderr, 'add', filepath, *parameters) expected_status = svntest.wc.State(sbox.wc_dir, {filename: Item(status='? ')}) run_and_verify_unquiet_status(filepath, expected_status)
def fail_add_mixed_eol_style(sbox): "fail to add a file with mixed EOL style" from svntest.actions import run_and_verify_svn, run_and_verify_unquiet_status # Bootstrap sbox.build() filename = "mixed-eol.txt" filepath = os.path.join(sbox.wc_dir, filename) parameters = ["--auto-props", "--config-option=config:auto-props:" + filename + "=svn:eol-style=native"] svntest.main.file_write(filepath, "foo\nbar\r\nbaz\r") expected_stderr = ( "svn: E200009: File '.*" + filename + "' has inconsistent newlines" + "|" + "svn: E135000: Inconsistent line ending style\n" ) run_and_verify_svn(None, [], expected_stderr, "add", filepath, *parameters) expected_status = svntest.wc.State(sbox.wc_dir, {filename: Item(status="? ")}) run_and_verify_unquiet_status(filepath, expected_status)
def svn_delete(self, rpath, even_if_modified=False): "Delete a WC path locally." lpath = local_path(rpath) args = [] if even_if_modified: args += ['--force'] actions.run_and_verify_svn(None, [], 'delete', lpath, *args)
def fail_add_mixed_eol_style(sbox): "fail to add a file with mixed EOL style" from svntest.actions import run_and_verify_svn, run_and_verify_unquiet_status # Bootstrap sbox.build() filename = 'mixed-eol.txt' filepath = os.path.join(sbox.wc_dir, filename) parameters = ['--auto-props', '--config-option=config:auto-props:' + filename + '=svn:eol-style=native'] svntest.main.file_write(filepath, 'foo\nbar\r\nbaz\r') expected_stderr = "svn: E200009: File '.*" + filename + \ "' has inconsistent newlines" + \ "|" + "svn: E135000: Inconsistent line ending style\n" run_and_verify_svn([], expected_stderr, 'add', filepath, *parameters) expected_status = svntest.wc.State(sbox.wc_dir, {filename : Item(status='? ')}) run_and_verify_unquiet_status(filepath, expected_status)
def svn_mkdir(self, rpath): lpath = local_path(rpath) actions.run_and_verify_svn(None, None, [], 'mkdir', lpath) self.state.add({ rpath : wc.StateItem(status='A ') })
def svn_commit(self, rpath='', log=''): "Commit a WC path (recursively). Return the new revision number." lpath = local_path(rpath) actions.run_and_verify_svn(verify.AnyOutput, [], 'commit', '-m', log, lpath) actions.run_and_verify_update(lpath, None, None, None) self.repo.head_rev += 1 return self.repo.head_rev
def svn_commit(self, rpath='', log=''): "Commit a WC path (recursively). Return the new revision number." lpath = local_path(rpath) actions.run_and_verify_svn(None, verify.AnyOutput, [], 'commit', '-m', log, lpath) actions.run_and_verify_update(lpath, None, None, None) self.repo.head_rev += 1 return self.repo.head_rev
def svn_mkdirs(self, *dirs): """Run 'svn mkdir' on the repository. DIRS is a list of directories to make, and each directory is a path relative to the repository root, neither starting nor ending with a slash.""" urls = [self.repo_url + '/' + dir for dir in dirs] actions.run_and_verify_svn(None, [], 'mkdir', '-m', 'svn_mkdirs()', '--parents', *urls) self.head_rev += 1
def check_mergeinfo_recursively(root_path, subpaths_mergeinfo): """Check that the mergeinfo properties on and under ROOT_PATH are those in SUBPATHS_MERGEINFO, a {path: mergeinfo-prop-val} dictionary.""" expected = verify.UnorderedOutput([ path + ' - ' + subpaths_mergeinfo[path] + '\n' for path in subpaths_mergeinfo ]) actions.run_and_verify_svn(expected, [], 'propget', '-R', SVN_PROP_MERGEINFO, root_path)
def check_mergeinfo_recursively(root_path, subpaths_mergeinfo): """Check that the mergeinfo properties on and under ROOT_PATH are those in SUBPATHS_MERGEINFO, a {path: mergeinfo-prop-val} dictionary.""" expected = verify.UnorderedOutput( [path + ' - ' + subpaths_mergeinfo[path] + '\n' for path in subpaths_mergeinfo]) actions.run_and_verify_svn(expected, [], 'propget', '-R', SVN_PROP_MERGEINFO, root_path)
def svn_mkfile(path): "Make and add a file with some default content, and keyword expansion." path = local_path(path) dirname, filename = os.path.split(path) main.file_write(path, "This is the file '" + filename + "'.\n" + "Last changed in '$Revision$'.\n") actions.run_and_verify_svn(None, [], 'add', path) actions.run_and_verify_svn(None, [], 'propset', 'svn:keywords', 'Revision', path)
def svn_mkdirs(self, *dirs): """Run 'svn mkdir' on the repository. DIRS is a list of directories to make, and each directory is a path relative to the repository root, neither starting nor ending with a slash.""" urls = [self.repo_url + '/' + dir for dir in dirs] actions.run_and_verify_svn(None, None, [], 'mkdir', '-m', 'svn_mkdirs()', '--parents', *urls) self.head_rev += 1
def svn_merge(rev_range, source, target, lines=None, elides=[], text_conflicts=0, prop_conflicts=0, tree_conflicts=0, text_resolved=0, prop_resolved=0, tree_resolved=0, args=[]): """Merge a single change from path SOURCE to path TARGET and verify the output and that there is no error. (The changes made are not verified.) REV_RANGE is either a number (to cherry-pick that specific change) or a two-element list [X,Y] to pick the revision range '-r(X-1):Y'. LINES is a list of regular expressions to match other lines of output; if LINES is 'None' then match all normal (non-conflicting) merges. ELIDES is a list of paths on which mergeinfo elision should be reported. TEXT_CONFLICTS, PROP_CONFLICTS and TREE_CONFLICTS specify the number of each kind of conflict to expect. ARGS are additional arguments passed to svn merge. """ source = local_path(source) target = local_path(target) elides = [local_path(p) for p in elides] if isinstance(rev_range, int): mi_rev_range = [rev_range] rev_arg = '-c' + str(rev_range) else: mi_rev_range = rev_range rev_arg = '-r' + str(rev_range[0] - 1) + ':' + str(rev_range[1]) if lines is None: lines = ["(A |D |[UG] | [UG]|[UG][UG]) " + target + ".*\n"] else: # Expect mergeinfo on the target; caller must supply matches for any # subtree mergeinfo paths. lines.append(" [UG] " + target + "\n") exp_out = expected_merge_output([mi_rev_range], lines, target=target, elides=elides, text_conflicts=text_conflicts, prop_conflicts=prop_conflicts, tree_conflicts=tree_conflicts, text_resolved=text_resolved, prop_resolved=prop_resolved, tree_resolved=tree_resolved) actions.run_and_verify_svn(exp_out, [], 'merge', rev_arg, source, target, '--accept=postpone', *args)
def svn_set_props(self, rpath, props): """Change the properties of PATH to be the dictionary {name -> value} PROPS. """ lpath = local_path(rpath) #for prop in path's existing props: # actions.run_and_verify_svn(None, None, [], 'propdel', # prop, lpath) for prop in props: actions.run_and_verify_svn(None, None, [], 'propset', prop, props[prop], lpath) self.state.tweak(rpath, props=props)
def svn_set_props(self, rpath, props): """Change the properties of PATH to be the dictionary {name -> value} PROPS. """ lpath = local_path(rpath) #for prop in path's existing props: # actions.run_and_verify_svn(None, [], 'propdel', # prop, lpath) for prop in props: actions.run_and_verify_svn(None, [], 'propset', prop, props[prop], lpath) self.state.tweak(rpath, props=props)
def svn_move(self, rpath1, rpath2, parents=False): """Move/rename the existing WC item RPATH1 to become RPATH2. RPATH2 must not already exist. If PARENTS is true, any missing parents of RPATH2 will be created.""" lpath1 = local_path(rpath1) lpath2 = local_path(rpath2) args = [lpath1, lpath2] if parents: args += ['--parents'] actions.run_and_verify_svn(None, [], 'copy', *args) self.state.add({rpath2: self.state.desc[rpath1]}) self.state.remove(rpath1)
def run_svn(sbox, expected_status, expected_stderr, *varargs): if expected_stderr is None: expected_stderr = [] cwd = os.getcwd() try: os.chdir(sbox.wc_dir) actions.run_and_verify_svn(None, expected_stderr, *varargs) finally: os.chdir(cwd) if expected_status is not None: actions.run_and_verify_status(sbox.wc_dir, expected_status)
def svn_move(self, rpath1, rpath2, parents=False): """Move/rename the existing WC item RPATH1 to become RPATH2. RPATH2 must not already exist. If PARENTS is true, any missing parents of RPATH2 will be created.""" lpath1 = local_path(rpath1) lpath2 = local_path(rpath2) args = [lpath1, lpath2] if parents: args += ['--parents'] actions.run_and_verify_svn(None, None, [], 'copy', *args) self.state.add({ rpath2: self.state.desc[rpath1] }) self.state.remove(rpath1)
def svn_copy(self, rpath1, rpath2, parents=False, rev=None): """Copy the existing WC item RPATH1 to become RPATH2. RPATH2 must not already exist. If PARENTS is true, any missing parents of RPATH2 will be created. If REV is not None, copy revision REV of the node identified by WC item RPATH1.""" lpath1 = local_path(rpath1) lpath2 = local_path(rpath2) args = [lpath1, lpath2] if rev is not None: args += ['-r', rev] if parents: args += ['--parents'] actions.run_and_verify_svn(None, [], 'copy', *args) self.state.add({rpath2: self.state.desc[rpath1]})
def svn_file_create_add(self, rpath, content=None, props=None): "Make and add a file with some default content, and keyword expansion." lpath = local_path(rpath) ldirname, filename = os.path.split(lpath) if content is None: # Default content content = "This is the file '" + filename + "'.\n" + \ "Last changed in '$Revision$'.\n" main.file_write(lpath, content) actions.run_and_verify_svn(None, [], 'add', lpath) self.state.add({rpath: wc.StateItem(status='A ')}) if props is None: # Default props props = {'svn:keywords': 'Revision'} self.svn_set_props(rpath, props)
def svn_copy(self, rpath1, rpath2, parents=False, rev=None): """Copy the existing WC item RPATH1 to become RPATH2. RPATH2 must not already exist. If PARENTS is true, any missing parents of RPATH2 will be created. If REV is not None, copy revision REV of the node identified by WC item RPATH1.""" lpath1 = local_path(rpath1) lpath2 = local_path(rpath2) args = [lpath1, lpath2] if rev is not None: args += ['-r', rev] if parents: args += ['--parents'] actions.run_and_verify_svn(None, None, [], 'copy', *args) self.state.add({ rpath2: self.state.desc[rpath1] })
def copy_A(dest_name, rev): expected = verify.UnorderedOutput([ "A " + sbox.ospath(path_join(dest_name, p)) + "\n" for p in A_paths ]) expected_status.add({ path_join(dest_name, p): Item(status=' ', wc_rev=rev) for p in A_paths }) expected_disk.add( {path_join(dest_name, p): greek_file_item(p) for p in A_paths}) # Make a branch A_COPY to merge into. actions.run_and_verify_svn(expected, [], 'copy', sbox.repo_url + "/A", os.path.join(wc_dir, dest_name)) expected_output = wc.State(wc_dir, {dest_name: Item(verb='Adding')}) actions.run_and_verify_commit(wc_dir, expected_output, expected_status)
def copy_A(dest_name, rev): expected = verify.UnorderedOutput( [ "A " + sbox.ospath(path_join(dest_name, p)) + "\n" for p in A_paths ]) expected_status.add( { path_join(dest_name, p) : Item(status=' ', wc_rev=rev) for p in A_paths }) expected_disk.add( { path_join(dest_name, p) : greek_file_item(p) for p in A_paths }) # Make a branch A_COPY to merge into. actions.run_and_verify_svn(expected, [], 'copy', sbox.repo_url + "/A", os.path.join(wc_dir, dest_name)) expected_output = wc.State(wc_dir, {dest_name : Item(verb='Adding')}) actions.run_and_verify_commit(wc_dir, expected_output, expected_status)
def svn_file_create_add(self, rpath, content=None, props=None): "Make and add a file with some default content, and keyword expansion." lpath = local_path(rpath) ldirname, filename = os.path.split(lpath) if content is None: # Default content content = "This is the file '" + filename + "'.\n" + \ "Last changed in '$Revision$'.\n" main.file_write(lpath, content) actions.run_and_verify_svn(None, None, [], 'add', lpath) self.state.add({ rpath : wc.StateItem(status='A ') }) if props is None: # Default props props = { 'svn:keywords': 'Revision' } self.svn_set_props(rpath, props)
def set_up_repos(wc_dir, br_dir, scenarios): if not os.path.exists(br_dir): main.run_svn(None, "mkdir", "--parents", br_dir) # create the file F1 and dir D1 which the tests regard as pre-existing paths = incoming_paths(wc_dir, wc_dir) # second arg is bogus but unimportant F1 = paths['F1'] # existing file to copy from main.file_write(F1, "This is initially file F1.\n") main.run_svn(None, 'add', F1) D1 = paths['D1'] # existing dir to copy from main.run_svn(None, 'mkdir', D1) # create the initial parent dirs, and each file or dir unless to-be-added for init_mods, action_mods in scenarios: path = "_".join(action_mods) P = os.path.join(br_dir, path) # parent of items to be tested main.run_svn(None, 'mkdir', '--parents', P) for modaction in init_mods: modify(modaction, incoming_paths(wc_dir, P)) run_and_verify_svn(None, AnyOutput, [], 'commit', '-m', 'Initial set-up.', wc_dir) # Capture the revision number init_rev = 2 ### hard-coded # modify all files and dirs in their various ways for _path, action_mods in scenarios: path = "_".join(action_mods) P = os.path.join(br_dir, path) # parent for modaction in action_mods: modify(modaction, incoming_paths(wc_dir, P)) # commit all the modifications run_and_verify_svn(None, AnyOutput, [], 'commit', '-m', 'Action.', wc_dir) # Capture the revision number changed_rev = 3 ### hard-coded return (init_rev, changed_rev)
def set_up_repos(wc_dir, br_dir, scenarios): if not os.path.exists(br_dir): main.run_svn(None, "mkdir", "--parents", br_dir) # create the file F1 and dir D1 which the tests regard as pre-existing paths = incoming_paths(wc_dir, wc_dir) # second arg is bogus but unimportant F1 = paths["F1"] # existing file to copy from main.file_write(F1, "This is initially file F1.\n") main.run_svn(None, "add", F1) D1 = paths["D1"] # existing dir to copy from main.run_svn(None, "mkdir", D1) # create the initial parent dirs, and each file or dir unless to-be-added for init_mods, action_mods in scenarios: path = "_".join(action_mods) P = os.path.join(br_dir, path) # parent of items to be tested main.run_svn(None, "mkdir", "--parents", P) for modaction in init_mods: modify(modaction, incoming_paths(wc_dir, P)) run_and_verify_svn(None, AnyOutput, [], "commit", "-m", "Initial set-up.", wc_dir) # Capture the revision number init_rev = 2 ### hard-coded # modify all files and dirs in their various ways for _path, action_mods in scenarios: path = "_".join(action_mods) P = os.path.join(br_dir, path) # parent for modaction in action_mods: modify(modaction, incoming_paths(wc_dir, P)) # commit all the modifications run_and_verify_svn(None, AnyOutput, [], "commit", "-m", "Action.", wc_dir) # Capture the revision number changed_rev = 3 ### hard-coded return (init_rev, changed_rev)
def get_mergeinfo_change(sbox, target): """Return a list of revision numbers representing the mergeinfo change on TARGET (working version against base). Non-recursive.""" exit, out, err = actions.run_and_verify_svn(None, None, [], 'diff', '--depth=empty', sbox.ospath(target)) merged_revs = [] for line in out: match = re.match(r' Merged /(\w+):r(.*)', line) if match: for r_range in match.group(2).split(','): if '-' in r_range: r_start, r_end = r_range.split('-') else: r_start = r_end = r_range merged_revs += range(int(r_start), int(r_end) + 1) return merged_revs
def get_mergeinfo_change(sbox, target): """Return a list of revision numbers representing the mergeinfo change on TARGET (working version against base). Non-recursive.""" exit, out, err = actions.run_and_verify_svn(None, [], 'diff', '--depth=empty', sbox.ospath(target)) merged_revs = [] for line in out: match = re.match(r' Merged /(\w+):r(.*)', line) if match: for r_range in match.group(2).split(','): if '-' in r_range: r_start, r_end = r_range.split('-') else: r_start = r_end = r_range merged_revs += range(int(r_start), int(r_end) + 1) return merged_revs
def set_up_dir_replace(sbox): """Set up the working copy for directory replace tests, creating directory 'A/B/F/foo' with files 'new file' and 'new file2' within it (r2), and merging 'foo' onto 'C' (r3), then deleting 'A/B/F/foo' (r4).""" sbox.build() wc_dir = sbox.wc_dir C_path = sbox.ospath('A/C') F_path = sbox.ospath('A/B/F') F_url = sbox.repo_url + '/A/B/F' foo_path = os.path.join(F_path, 'foo') new_file = os.path.join(foo_path, "new file") new_file2 = os.path.join(foo_path, "new file 2") # Make directory foo in F, and add some files within it. actions.run_and_verify_svn(None, [], 'mkdir', foo_path) main.file_append(new_file, "Initial text in new file.\n") main.file_append(new_file2, "Initial text in new file 2.\n") main.run_svn(None, "add", new_file) main.run_svn(None, "add", new_file2) # Commit all the new content, creating r2. expected_output = wc.State( wc_dir, { 'A/B/F/foo': Item(verb='Adding'), 'A/B/F/foo/new file': Item(verb='Adding'), 'A/B/F/foo/new file 2': Item(verb='Adding'), }) expected_status = actions.get_virginal_state(wc_dir, 1) expected_status.add({ 'A/B/F/foo': Item(status=' ', wc_rev=2), 'A/B/F/foo/new file': Item(status=' ', wc_rev=2), 'A/B/F/foo/new file 2': Item(status=' ', wc_rev=2), }) actions.run_and_verify_commit(wc_dir, expected_output, expected_status) # Merge foo onto C expected_output = wc.State( C_path, { 'foo': Item(status='A '), 'foo/new file': Item(status='A '), 'foo/new file 2': Item(status='A '), }) expected_mergeinfo_output = wc.State(C_path, { '': Item(status=' U'), }) expected_elision_output = wc.State(C_path, {}) expected_disk = wc.State( '', { '': Item(props={SVN_PROP_MERGEINFO: '/A/B/F:2'}), 'foo': Item(), 'foo/new file': Item("Initial text in new file.\n"), 'foo/new file 2': Item("Initial text in new file 2.\n"), }) expected_status = wc.State( C_path, { '': Item(status=' M', wc_rev=1), 'foo': Item(status='A ', wc_rev='-', copied='+'), 'foo/new file': Item(status=' ', wc_rev='-', copied='+'), 'foo/new file 2': Item(status=' ', wc_rev='-', copied='+'), }) expected_skip = wc.State(C_path, {}) actions.run_and_verify_merge(C_path, '1', '2', F_url, None, expected_output, expected_mergeinfo_output, expected_elision_output, expected_disk, expected_status, expected_skip, check_props=True) # Commit merge of foo onto C, creating r3. expected_output = wc.State(wc_dir, { 'A/C': Item(verb='Sending'), 'A/C/foo': Item(verb='Adding'), }) expected_status = actions.get_virginal_state(wc_dir, 1) expected_status.add({ 'A/B/F/foo': Item(status=' ', wc_rev=2), 'A/C': Item(status=' ', wc_rev=3), 'A/B/F/foo/new file': Item(status=' ', wc_rev=2), 'A/B/F/foo/new file 2': Item(status=' ', wc_rev=2), 'A/C/foo': Item(status=' ', wc_rev=3), 'A/C/foo/new file': Item(status=' ', wc_rev=3), 'A/C/foo/new file 2': Item(status=' ', wc_rev=3), }) actions.run_and_verify_commit(wc_dir, expected_output, expected_status) # Delete foo on F, creating r4. actions.run_and_verify_svn(None, [], 'rm', foo_path) expected_output = wc.State(wc_dir, { 'A/B/F/foo': Item(verb='Deleting'), }) expected_status = actions.get_virginal_state(wc_dir, 1) expected_status.add({ 'A/C': Item(status=' ', wc_rev=3), 'A/C/foo': Item(status=' ', wc_rev=3), 'A/C/foo/new file': Item(status=' ', wc_rev=3), 'A/C/foo/new file 2': Item(status=' ', wc_rev=3), }) actions.run_and_verify_commit(wc_dir, expected_output, expected_status)
def svn_copy(s_rev, path1, path2): "Copy a WC path locally." path1 = local_path(path1) path2 = local_path(path2) actions.run_and_verify_svn(None, [], 'copy', '--parents', '-r', s_rev, path1, path2)
def ensure_tree_conflict(sbox, operation, incoming_scenarios, localmod_scenarios, commit_local_mods): sbox.build() wc_dir = sbox.wc_dir def url_of(repo_relative_path): return sbox.repo_url + "/" + repo_relative_path verbose_print("") verbose_print("=== Starting a set of '" + operation + "' tests.") # Path to source branch, relative to wc_dir. # Source is where the "incoming" mods are made. source_br = "branch1" verbose_print("--- Creating changes in repos") source_wc_dir = os.path.join(wc_dir, source_br) source_left_rev, source_right_rev = set_up_repos(wc_dir, source_wc_dir, incoming_scenarios) head_rev = source_right_rev ### assumption # Local mods are the outer loop because cleaning up the WC is slow # ('svn revert' isn't sufficient because it leaves unversioned files) for _loc_init_mods, loc_action in localmod_scenarios: # Determine the branch (directory) in which local mods will be made. if operation == "update": # Path to target branch (where conflicts are raised), relative to wc_dir. target_br = source_br target_start_rev = source_left_rev else: # switch/merge # Make, and work in, a "branch2" that is a copy of "branch1". target_br = "branch2" run_and_verify_svn( None, AnyOutput, [], "copy", "-r", str(source_left_rev), url_of(source_br), url_of(target_br), "-m", "Create target branch.", ) head_rev += 1 target_start_rev = head_rev main.run_svn(None, "checkout", "-r", str(target_start_rev), sbox.repo_url, wc_dir) saved_cwd = os.getcwd() os.chdir(wc_dir) for _inc_init_mods, inc_action in incoming_scenarios: scen_name = "_".join(inc_action) source_url = url_of(source_br + "/" + scen_name) target_path = os.path.join(target_br, scen_name) verbose_print("=== " + str(inc_action) + " onto " + str(loc_action)) verbose_print("--- Making local mods") for modaction in loc_action: modify(modaction, localmod_paths(".", target_path)) if commit_local_mods: run_and_verify_svn(None, AnyOutput, [], "commit", target_path, "-m", "Mods in target branch.") head_rev += 1 # What do we want to test for? (This selection could in future be # passed in to this function as a parameter.) test_what = [ "commit-ood", "action", # required for any of the following ones to work "notify", "commit-c", "status-c", "resolve", # required for any of the following ones to work "status-nc", #'commit-ok', ] if "commit-ood" in test_what: # For update, verify the pre-condition that WC is out of date. # For switch/merge, there is no such precondition. if operation == "update": verbose_print("--- Trying to commit (expecting 'out-of-date' error)") run_and_verify_commit(".", None, None, "Commit failed", target_path) if modaction.startswith("f"): victim = os.path.join(target_path, "F") else: victim = os.path.join(target_path, "D") # Perform the operation that tries to apply incoming changes to the WC. # The command is expected to do something (and give some output), # and it should raise a conflict but not an error. if "action" in test_what: # Determine what notification to expect if "notify" in test_what: expected_stdout = svntest.verify.ExpectedOutput(" C " + victim + "\n", match_all=False) else: expected_stdout = svntest.verify.AnyOutput # Do the main action if operation == "update": verbose_print("--- Updating") run_and_verify_svn(None, expected_stdout, [], "update", target_path) elif operation == "switch": verbose_print("--- Switching") run_and_verify_svn(None, expected_stdout, [], "switch", source_url, target_path) elif operation == "merge": verbose_print("--- Merging") run_and_verify_svn( None, expected_stdout, [], "merge", "--ignore-ancestry", "-r", str(source_left_rev) + ":" + str(source_right_rev), source_url, target_path, ) else: raise Exception("unknown operation: '" + operation + "'") if "commit-c" in test_what: verbose_print("--- Trying to commit (expecting 'conflict' error)") ### run_and_verify_commit() requires an "output_tree" argument, but # here we get away with passing None because we know an implementation # detail: namely that it's not going to look at that argument if it # gets the stderr that we're expecting. run_and_verify_commit(".", None, None, ".*conflict.*", victim) if "status-c" in test_what: verbose_print("--- Checking that 'status' reports the conflict") expected_stdout = svntest.verify.RegexOutput("^......C.* " + re.escape(victim) + "$", match_all=False) run_and_verify_svn(None, expected_stdout, [], "status", victim) if "resolve" in test_what: verbose_print("--- Resolving the conflict") # Make sure resolving the parent does nothing. run_and_verify_resolved([], os.path.dirname(victim)) # The real resolved call. run_and_verify_resolved([victim]) if "status-nc" in test_what: verbose_print("--- Checking that 'status' does not report a conflict") exitcode, stdout, stderr = run_and_verify_svn(None, None, [], "status", victim) for line in stdout: if line[6] == "C": # and line.endswith(victim + '\n'): raise svntest.Failure("unexpected status C") # on path '" + victim + "'") if "commit-ok" in test_what: verbose_print("--- Committing (should now succeed)") run_and_verify_svn(None, None, [], "commit", "-m", "", target_path) target_start_rev += 1 verbose_print("") os.chdir(saved_cwd) # Clean up the target branch and WC main.run_svn(None, "revert", "-R", wc_dir) main.safe_rmtree(wc_dir) if operation != "update": run_and_verify_svn(None, AnyOutput, [], "delete", url_of(target_br), "-m", "Delete target branch.") head_rev += 1
def set_up_dir_replace(sbox): """Set up the working copy for directory replace tests, creating directory 'A/B/F/foo' with files 'new file' and 'new file2' within it (r2), and merging 'foo' onto 'C' (r3), then deleting 'A/B/F/foo' (r4).""" sbox.build() wc_dir = sbox.wc_dir C_path = sbox.ospath('A/C') F_path = sbox.ospath('A/B/F') F_url = sbox.repo_url + '/A/B/F' foo_path = os.path.join(F_path, 'foo') new_file = os.path.join(foo_path, "new file") new_file2 = os.path.join(foo_path, "new file 2") # Make directory foo in F, and add some files within it. actions.run_and_verify_svn(None, [], 'mkdir', foo_path) main.file_append(new_file, "Initial text in new file.\n") main.file_append(new_file2, "Initial text in new file 2.\n") main.run_svn(None, "add", new_file) main.run_svn(None, "add", new_file2) # Commit all the new content, creating r2. expected_output = wc.State(wc_dir, { 'A/B/F/foo' : Item(verb='Adding'), 'A/B/F/foo/new file' : Item(verb='Adding'), 'A/B/F/foo/new file 2' : Item(verb='Adding'), }) expected_status = actions.get_virginal_state(wc_dir, 1) expected_status.add({ 'A/B/F/foo' : Item(status=' ', wc_rev=2), 'A/B/F/foo/new file' : Item(status=' ', wc_rev=2), 'A/B/F/foo/new file 2' : Item(status=' ', wc_rev=2), }) actions.run_and_verify_commit(wc_dir, expected_output, expected_status) # Merge foo onto C expected_output = wc.State(C_path, { 'foo' : Item(status='A '), 'foo/new file' : Item(status='A '), 'foo/new file 2' : Item(status='A '), }) expected_mergeinfo_output = wc.State(C_path, { '' : Item(status=' U'), }) expected_elision_output = wc.State(C_path, { }) expected_disk = wc.State('', { '' : Item(props={SVN_PROP_MERGEINFO : '/A/B/F:2'}), 'foo' : Item(), 'foo/new file' : Item("Initial text in new file.\n"), 'foo/new file 2' : Item("Initial text in new file 2.\n"), }) expected_status = wc.State(C_path, { '' : Item(status=' M', wc_rev=1), 'foo' : Item(status='A ', wc_rev='-', copied='+'), 'foo/new file' : Item(status=' ', wc_rev='-', copied='+'), 'foo/new file 2' : Item(status=' ', wc_rev='-', copied='+'), }) expected_skip = wc.State(C_path, { }) actions.run_and_verify_merge(C_path, '1', '2', F_url, None, expected_output, expected_mergeinfo_output, expected_elision_output, expected_disk, expected_status, expected_skip, check_props=True) # Commit merge of foo onto C, creating r3. expected_output = wc.State(wc_dir, { 'A/C' : Item(verb='Sending'), 'A/C/foo' : Item(verb='Adding'), }) expected_status = actions.get_virginal_state(wc_dir, 1) expected_status.add({ 'A/B/F/foo' : Item(status=' ', wc_rev=2), 'A/C' : Item(status=' ', wc_rev=3), 'A/B/F/foo/new file' : Item(status=' ', wc_rev=2), 'A/B/F/foo/new file 2' : Item(status=' ', wc_rev=2), 'A/C/foo' : Item(status=' ', wc_rev=3), 'A/C/foo/new file' : Item(status=' ', wc_rev=3), 'A/C/foo/new file 2' : Item(status=' ', wc_rev=3), }) actions.run_and_verify_commit(wc_dir, expected_output, expected_status) # Delete foo on F, creating r4. actions.run_and_verify_svn(None, [], 'rm', foo_path) expected_output = wc.State(wc_dir, { 'A/B/F/foo' : Item(verb='Deleting'), }) expected_status = actions.get_virginal_state(wc_dir, 1) expected_status.add({ 'A/C' : Item(status=' ', wc_rev=3), 'A/C/foo' : Item(status=' ', wc_rev=3), 'A/C/foo/new file' : Item(status=' ', wc_rev=3), 'A/C/foo/new file 2' : Item(status=' ', wc_rev=3), }) actions.run_and_verify_commit(wc_dir, expected_output, expected_status)
def copy_A(dest_name, rev): expected = verify.UnorderedOutput([ "A " + os.path.join(wc_dir, dest_name, "B") + "\n", "A " + os.path.join(wc_dir, dest_name, "B", "lambda") + "\n", "A " + os.path.join(wc_dir, dest_name, "B", "E") + "\n", "A " + os.path.join(wc_dir, dest_name, "B", "E", "alpha") + "\n", "A " + os.path.join(wc_dir, dest_name, "B", "E", "beta") + "\n", "A " + os.path.join(wc_dir, dest_name, "B", "F") + "\n", "A " + os.path.join(wc_dir, dest_name, "mu") + "\n", "A " + os.path.join(wc_dir, dest_name, "C") + "\n", "A " + os.path.join(wc_dir, dest_name, "D") + "\n", "A " + os.path.join(wc_dir, dest_name, "D", "gamma") + "\n", "A " + os.path.join(wc_dir, dest_name, "D", "G") + "\n", "A " + os.path.join(wc_dir, dest_name, "D", "G", "pi") + "\n", "A " + os.path.join(wc_dir, dest_name, "D", "G", "rho") + "\n", "A " + os.path.join(wc_dir, dest_name, "D", "G", "tau") + "\n", "A " + os.path.join(wc_dir, dest_name, "D", "H") + "\n", "A " + os.path.join(wc_dir, dest_name, "D", "H", "chi") + "\n", "A " + os.path.join(wc_dir, dest_name, "D", "H", "omega") + "\n", "A " + os.path.join(wc_dir, dest_name, "D", "H", "psi") + "\n", "Checked out revision " + str(rev - 1) + ".\n", "A " + os.path.join(wc_dir, dest_name) + "\n" ]) expected_status.add({ dest_name + "/B": Item(status=' ', wc_rev=rev), dest_name + "/B/lambda": Item(status=' ', wc_rev=rev), dest_name + "/B/E": Item(status=' ', wc_rev=rev), dest_name + "/B/E/alpha": Item(status=' ', wc_rev=rev), dest_name + "/B/E/beta": Item(status=' ', wc_rev=rev), dest_name + "/B/F": Item(status=' ', wc_rev=rev), dest_name + "/mu": Item(status=' ', wc_rev=rev), dest_name + "/C": Item(status=' ', wc_rev=rev), dest_name + "/D": Item(status=' ', wc_rev=rev), dest_name + "/D/gamma": Item(status=' ', wc_rev=rev), dest_name + "/D/G": Item(status=' ', wc_rev=rev), dest_name + "/D/G/pi": Item(status=' ', wc_rev=rev), dest_name + "/D/G/rho": Item(status=' ', wc_rev=rev), dest_name + "/D/G/tau": Item(status=' ', wc_rev=rev), dest_name + "/D/H": Item(status=' ', wc_rev=rev), dest_name + "/D/H/chi": Item(status=' ', wc_rev=rev), dest_name + "/D/H/omega": Item(status=' ', wc_rev=rev), dest_name + "/D/H/psi": Item(status=' ', wc_rev=rev), dest_name: Item(status=' ', wc_rev=rev) }) expected_disk.add({ dest_name: Item(), dest_name + '/B': Item(), dest_name + '/B/lambda': Item("This is the file 'lambda'.\n"), dest_name + '/B/E': Item(), dest_name + '/B/E/alpha': Item("This is the file 'alpha'.\n"), dest_name + '/B/E/beta': Item("This is the file 'beta'.\n"), dest_name + '/B/F': Item(), dest_name + '/mu': Item("This is the file 'mu'.\n"), dest_name + '/C': Item(), dest_name + '/D': Item(), dest_name + '/D/gamma': Item("This is the file 'gamma'.\n"), dest_name + '/D/G': Item(), dest_name + '/D/G/pi': Item("This is the file 'pi'.\n"), dest_name + '/D/G/rho': Item("This is the file 'rho'.\n"), dest_name + '/D/G/tau': Item("This is the file 'tau'.\n"), dest_name + '/D/H': Item(), dest_name + '/D/H/chi': Item("This is the file 'chi'.\n"), dest_name + '/D/H/omega': Item("This is the file 'omega'.\n"), dest_name + '/D/H/psi': Item("This is the file 'psi'.\n"), }) # Make a branch A_COPY to merge into. actions.run_and_verify_svn(expected, [], 'copy', sbox.repo_url + "/A", os.path.join(wc_dir, dest_name)) expected_output = wc.State(wc_dir, {dest_name: Item(verb='Adding')}) actions.run_and_verify_commit(wc_dir, expected_output, expected_status)
def svn_modfile(path): "Make text and property mods to a WC file." path = local_path(path) main.file_append(path, "An extra line.\n") actions.run_and_verify_svn(None, [], 'propset', 'newprop', 'v', path)
def ensure_tree_conflict(sbox, operation, incoming_scenarios, localmod_scenarios, commit_local_mods): sbox.build() wc_dir = sbox.wc_dir def url_of(repo_relative_path): return sbox.repo_url + '/' + repo_relative_path verbose_print("") verbose_print("=== Starting a set of '" + operation + "' tests.") # Path to source branch, relative to wc_dir. # Source is where the "incoming" mods are made. source_br = "branch1" verbose_print("--- Creating changes in repos") source_wc_dir = os.path.join(wc_dir, source_br) source_left_rev, source_right_rev = set_up_repos(wc_dir, source_wc_dir, incoming_scenarios) head_rev = source_right_rev ### assumption # Local mods are the outer loop because cleaning up the WC is slow # ('svn revert' isn't sufficient because it leaves unversioned files) for _loc_init_mods, loc_action in localmod_scenarios: # Determine the branch (directory) in which local mods will be made. if operation == 'update': # Path to target branch (where conflicts are raised), relative to wc_dir. target_br = source_br target_start_rev = source_left_rev else: # switch/merge # Make, and work in, a "branch2" that is a copy of "branch1". target_br = "branch2" run_and_verify_svn(None, AnyOutput, [], 'copy', '-r', str(source_left_rev), url_of(source_br), url_of(target_br), '-m', 'Create target branch.') head_rev += 1 target_start_rev = head_rev main.run_svn(None, 'checkout', '-r', str(target_start_rev), sbox.repo_url, wc_dir) saved_cwd = os.getcwd() os.chdir(wc_dir) for _inc_init_mods, inc_action in incoming_scenarios: scen_name = "_".join(inc_action) source_url = url_of(source_br + '/' + scen_name) target_path = os.path.join(target_br, scen_name) verbose_print("=== " + str(inc_action) + " onto " + str(loc_action)) verbose_print("--- Making local mods") for modaction in loc_action: modify(modaction, localmod_paths(".", target_path)) if commit_local_mods: run_and_verify_svn(None, AnyOutput, [], 'commit', target_path, '-m', 'Mods in target branch.') head_rev += 1 # What do we want to test for? (This selection could in future be # passed in to this function as a parameter.) test_what = [ 'commit-ood', 'action', # required for any of the following ones to work 'notify', 'commit-c', 'status-c', 'resolve', # required for any of the following ones to work 'status-nc', #'commit-ok', ] if 'commit-ood' in test_what: # For update, verify the pre-condition that WC is out of date. # For switch/merge, there is no such precondition. if operation == 'update': verbose_print("--- Trying to commit (expecting 'out-of-date' error)") run_and_verify_commit(".", None, None, "Commit failed", target_path) if modaction.startswith('f'): victim = os.path.join(target_path, 'F') else: victim = os.path.join(target_path, 'D') # Perform the operation that tries to apply incoming changes to the WC. # The command is expected to do something (and give some output), # and it should raise a conflict but not an error. if 'action' in test_what: # Determine what notification to expect if 'notify' in test_what: expected_stdout = svntest.verify.ExpectedOutput(" C " + victim + "\n", match_all=False) else: expected_stdout = svntest.verify.AnyOutput # Do the main action if operation == 'update': verbose_print("--- Updating") run_and_verify_svn(None, expected_stdout, [], 'update', target_path) elif operation == 'switch': verbose_print("--- Switching") run_and_verify_svn(None, expected_stdout, [], 'switch', source_url, target_path) elif operation == 'merge': verbose_print("--- Merging") run_and_verify_svn(None, expected_stdout, [], 'merge', '--ignore-ancestry', '-r', str(source_left_rev) + ':' + str(source_right_rev), source_url, target_path) else: raise Exception("unknown operation: '" + operation + "'") if 'commit-c' in test_what: verbose_print("--- Trying to commit (expecting 'conflict' error)") ### run_and_verify_commit() requires an "output_tree" argument, but # here we get away with passing None because we know an implementation # detail: namely that it's not going to look at that argument if it # gets the stderr that we're expecting. run_and_verify_commit(".", None, None, ".*conflict.*", victim) if 'status-c' in test_what: verbose_print("--- Checking that 'status' reports the conflict") expected_stdout = svntest.verify.RegexOutput("^......C.* " + re.escape(victim) + "$", match_all=False) run_and_verify_svn(None, expected_stdout, [], 'status', victim) if 'resolve' in test_what: verbose_print("--- Resolving the conflict") # Make sure resolving the parent does nothing. run_and_verify_resolved([], os.path.dirname(victim)) # The real resolved call. run_and_verify_resolved([victim]) if 'status-nc' in test_what: verbose_print("--- Checking that 'status' does not report a conflict") exitcode, stdout, stderr = run_and_verify_svn(None, None, [], 'status', victim) for line in stdout: if line[6] == 'C': # and line.endswith(victim + '\n'): raise svntest.Failure("unexpected status C") # on path '" + victim + "'") if 'commit-ok' in test_what: verbose_print("--- Committing (should now succeed)") run_and_verify_svn(None, None, [], 'commit', '-m', '', target_path) target_start_rev += 1 verbose_print("") os.chdir(saved_cwd) # Clean up the target branch and WC main.run_svn(None, 'revert', '-R', wc_dir) main.safe_rmtree(wc_dir) if operation != 'update': run_and_verify_svn(None, AnyOutput, [], 'delete', url_of(target_br), '-m', 'Delete target branch.') head_rev += 1