#!/usr/bin/env python # This script tests whether applying patches in funny orders works # # Copyright (C) 2005 Walter Landry # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 dated June, 1991. # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA import arx import os def removeall(top): for root, dirs, files in os.walk(top, topdown=False): for name in files: os.remove(os.path.join(root, name)) for name in dirs: os.rmdir(os.path.join(root, name)) os.rmdir(top) arx.make_archive("foo",arx.uri("foo"),0,"") os.mkdir("a") os.chdir("a") os.mkdir("foo") os.mkdir("bar") f=open("foo/a","w") f.close() arx.init(arx.Parsed_Name("foo/a"),arx.path("."),1) arx.commit_revision(arx.path("."),"init") arx.atomic_move(arx.path("foo/a"),arx.path("foo/b"),0) arx.commit_revision(arx.path("."),"a -> b") arx.atomic_move(arx.path("foo/b"),arx.path("bar/"),0) arx.commit_revision(arx.path("."),"foo/b -> bar/b") arx.atomic_move(arx.path("bar"),arx.path("baz"),0) arx.commit_revision(arx.path("."),"bar -> baz") arx.atomic_move(arx.path("foo"),arx.path("fbb"),0) arx.commit_revision(arx.path("."),"foo -> fbb") os.chdir("..") removeall("a") # Define lots of functions to do the work of applying the patches. def replay(name,directory): temp_dir=arx.Temp_Path(directory,"patch") arx.get_revision_patch(arx.Parsed_Name(name),temp_dir) if not (arx.do_patch(temp_dir,directory,0,1,1,1)).empty(): raise Exception("Conflict when applying function") def test_patches(patch_list): print patch_list arx.get_revision(arx.Parsed_Name("foo/a,0"),arx.path("b"),arx.path("."),1) os.chdir("b") replay("foo/a,"+patch_list[0],arx.path(".")) replay("foo/a,"+patch_list[1],arx.path(".")) replay("foo/a,"+patch_list[2],arx.path(".")) replay("foo/a,"+patch_list[3],arx.path(".")) def cleanup_patches(): os.chdir("..") removeall("b") def test_clean(patch_list): test_patches(patch_list) if not (os.path.isdir("baz") or os.path.isdir("fbb") or os.path.isfile("baz/b")): raise Exception("Replaying patches did not work") cleanup_patches() # Permutation code from Michael Davies on ASPN # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252178/index_txt # Released under the Python License. See permutation.LICENSE for details. def all_perms(str): if len(str) <=1: yield str else: for perm in all_perms(str[1:]): for i in range(len(perm)+1): yield perm[:i] + str[0:1] + perm[i:] for p in all_perms(["1","2","3","4"]): test_clean(p) # Now test that directory loop conflicts are handled appropriately # This tests a -> b/a merged (both ways) with b->a/b, a2 -> a/b/a. os.mkdir("parent") os.chdir("parent") os.mkdir("a") os.mkdir("b") os.mkdir("a2") arx.init(arx.Parsed_Name("foo/loop"),arx.path("."),1) arx.commit_revision(arx.path("."),"init") arx.atomic_move(arx.path("a"),arx.path("b/a"),0) arx.commit_revision(arx.path("."),"a -> b/a") os.chdir("..") removeall("parent") arx.get_revision(arx.Parsed_Name("foo/loop,0"),arx.path("f0"),arx.path("."),1) arx.fork(arx.Parsed_Name("foo/loop,0"),arx.Parsed_Name("foo/loop.1"), arx.path("f0")) os.chdir("f0") arx.atomic_move(arx.path("b"),arx.path("a/b"),0) arx.atomic_move(arx.path("a2"),arx.path("a/b/a"),0) arx.commit_revision(arx.path("."),"other moves") conflicts=arx.merge_branches(arx.Parsed_Name("foo/loop.1,0"), arx.Parsed_Name("foo/loop,1"), arx.Parsed_Name(), arx.path("."),arx.three_way,1,0) if((conflicts.directory_loop).empty()): raise Exception("Directory loop not detected in first test") os.chdir("..") removeall("f0") arx.get_revision(arx.Parsed_Name("foo/loop,1"),arx.path("f0"),arx.path("."),1) conflicts=arx.merge_branches(arx.Parsed_Name("foo/loop,1"), arx.Parsed_Name("foo/loop.1,0"), arx.Parsed_Name(), arx.path("f0"),arx.three_way,1,0) if((conflicts.directory_loop).empty()): raise Exception("Directory loop not detected in second test") removeall("f0") # Given this setup # # a/b/c # d/e/f # # Do these moves and deletes # # b -> f/b # e -> c/e # rm -rf d os.mkdir("parent") os.chdir("parent") os.mkdir("a") os.mkdir("b") os.mkdir("c") os.mkdir("d") os.mkdir("e") os.mkdir("f") arx.init(arx.Parsed_Name("foo/deleted-loop"),arx.path("."),1) arx.commit_revision(arx.path("."),"init") arx.atomic_move(arx.path("b"),arx.path("f/b"),0) arx.atomic_move(arx.path("e"),arx.path("c/e"),0) checksums=arx.Checksums() arx.read_checksums(arx.path("."),checksums) arx.delete_element(arx.path("d"),checksums,0,0,0,0) arx.commit_revision(arx.path("."),"moves") os.chdir("..") removeall("parent") arx.get_revision(arx.Parsed_Name("foo/deleted-loop,0"),arx.path("f0"), arx.path("."),1) os.chdir("f0") arx.atomic_move(arx.path("b"),arx.path("a/b"),0) arx.atomic_move(arx.path("c"),arx.path("a/b/c"),0) arx.atomic_move(arx.path("e"),arx.path("d/e"),0) arx.atomic_move(arx.path("f"),arx.path("d/e/f"),0) conflicts=arx.merge_branches(arx.Parsed_Name("foo/deleted-loop,0"), arx.Parsed_Name("foo/deleted-loop,1"), arx.Parsed_Name(), arx.path("."),arx.three_way,1,0) if(conflicts.directory_loop.empty()): raise Exception("Directory loop not detected in deleted loop test") if(conflicts.deleted_parent.empty()): raise Exception("Deleted parent not detected in deleted loop test") if(conflicts.move_parent.empty()): raise Exception("Deleted parent not detected in deleted loop test") os.chdir("..") removeall("f0") removeall("foo") arx.delete_archive_registration("foo")