[Notes] [Git][BuildStream/buildstream][jmac/cas_to_cas_oct] 2 commits: CAS-to-CAS: Now passing all 20x20 tests



Title: GitLab

Jim MacArthur pushed to branch jmac/cas_to_cas_oct at BuildStream / buildstream

Commits:

2 changed files:

Changes:

  • buildstream/storage/_casbaseddirectory.py
    ... ... @@ -298,6 +298,9 @@ class CasBasedDirectory(Directory):
    298 298
             else:
    
    299 299
                 if create:
    
    300 300
                     newdir = self._add_directory(subdirectory_spec[0])
    
    301
    +                print("Created new directory called {} and descending into it".format(subdirectory_spec[0]))
    
    302
    +                #if subdirectory_spec[0] == "broken":
    
    303
    +                #    assert False
    
    301 304
                     return newdir.descend(subdirectory_spec[1:], create)
    
    302 305
                 else:
    
    303 306
                     error = "No entry called '{}' found in {}. There are directories called {}."
    
    ... ... @@ -358,7 +361,7 @@ class CasBasedDirectory(Directory):
    358 361
             print("Is {} followable? Resolved to {}".format(name, target))
    
    359 362
             return isinstance(target, CasBasedDirectory) or target is None
    
    360 363
     
    
    361
    -    def _resolve_symlink(self, node):
    
    364
    +    def _resolve_symlink(self, node, force_create=True):
    
    362 365
             """Same as _resolve_symlink_or_directory but takes a SymlinkNode.
    
    363 366
             """
    
    364 367
     
    
    ... ... @@ -377,7 +380,10 @@ class CasBasedDirectory(Directory):
    377 380
                 elif c == "..":
    
    378 381
                     directory = directory.parent
    
    379 382
                 else:
    
    380
    -                directory = directory.descend(c, create=True)
    
    383
    +                if c in directory.index or force_create:
    
    384
    +                    directory = directory.descend(c, create=True)
    
    385
    +                else:
    
    386
    +                    return None
    
    381 387
             return directory
    
    382 388
     
    
    383 389
         
    
    ... ... @@ -400,6 +406,7 @@ class CasBasedDirectory(Directory):
    400 406
                 return index_entry.pb_object
    
    401 407
             
    
    402 408
             assert isinstance(index_entry.pb_object, remote_execution_pb2.SymlinkNode)
    
    409
    +        print("Resolving '{}': This is a symlink node in the current directory.".format(name))
    
    403 410
             symlink = index_entry.pb_object
    
    404 411
             components = symlink.target.split(CasBasedDirectory._pb2_path_sep)
    
    405 412
     
    
    ... ... @@ -443,7 +450,7 @@ class CasBasedDirectory(Directory):
    443 450
                             print("  resolving {}: file/broken link".format(c))
    
    444 451
                             if f is None and force_create:
    
    445 452
                                 print("Creating target of broken link {}".format(c))
    
    446
    -                            return directory.descend(c, create=True)
    
    453
    +                            directory = directory.descend(c, create=True)
    
    447 454
                             elif components:
    
    448 455
                                 # Oh dear. We have components left to resolve, but the one we're trying to resolve points to a file.
    
    449 456
                                 raise VirtualDirectoryError("Reached a file called {} while trying to resolve a symlink; cannot proceed".format(c))
    
    ... ... @@ -453,7 +460,7 @@ class CasBasedDirectory(Directory):
    453 460
                         print("  resolving {}: Non-existent file; must be from a broken symlink.".format(c))
    
    454 461
                         if force_create:
    
    455 462
                             print("Creating target of broken link {} (2)".format(c))
    
    456
    -                        return directory.descend(c, create=True)
    
    463
    +                        directory = directory.descend(c, create=True)
    
    457 464
                         else:
    
    458 465
                             return None
    
    459 466
     
    
    ... ... @@ -528,6 +535,8 @@ class CasBasedDirectory(Directory):
    528 535
                     directory_name = split_path[0]
    
    529 536
                     # Hand this off to the importer for that subdir. This will only do one file -
    
    530 537
                     # a better way would be to hand off all the files in this subdir at once.
    
    538
    +                # failed here because directory_name didn't point to a directory...
    
    539
    +                print("Attempting to import into {} from {}".format(directory_name, source_directory))
    
    531 540
                     subdir_result = self._import_directory_recursively(directory_name, source_directory,
    
    532 541
                                                                        split_path[1:], path_prefix)
    
    533 542
                     result.combine(subdir_result)
    
    ... ... @@ -598,7 +607,7 @@ class CasBasedDirectory(Directory):
    598 607
             return [f[len(dirname):] for f in sorted_files if f.startswith(dirname)]
    
    599 608
     
    
    600 609
         def symlink_target_is_directory(self, symlink_node):
    
    601
    -        x = self._resolve_symlink(symlink_node)
    
    610
    +        x = self._resolve_symlink(symlink_node, force_create=False)
    
    602 611
             return isinstance(x, CasBasedDirectory)
    
    603 612
     
    
    604 613
         def _verify_unique(self):
    
    ... ... @@ -636,14 +645,20 @@ class CasBasedDirectory(Directory):
    636 645
                         subcomponents = CasBasedDirectory.files_in_subdir(files, dirname)
    
    637 646
                         # We will fail at this point if there is a file or symlink to file called 'dirname'.
    
    638 647
                         if dirname in self.index:
    
    639
    -                        x = self._resolve(dirname)
    
    648
    +                        x = self._resolve(dirname, force_create=True)
    
    640 649
                             if isinstance(x, remote_execution_pb2.FileNode):
    
    641 650
                                 self.delete_entry(dirname)
    
    642 651
                                 result.overwritten.append(f)
    
    643
    -                    self.create_directory(dirname)
    
    644
    -                    print("Creating destination in {}: {}".format(self, dirname))
    
    645
    -                    dest_subdir = self._resolve_symlink_or_directory(dirname)
    
    652
    +                            dest_subdir = self.descend(dirname, create=True)
    
    653
    +                        else:
    
    654
    +                            dest_subdir = x
    
    655
    +                    else:
    
    656
    +                        print("Importing {}: {} does not exist in {}, so it is created as a directory".format(f, dirname, self))
    
    657
    +                        
    
    658
    +                        self.create_directory(dirname)
    
    659
    +                        dest_subdir = self._resolve_symlink_or_directory(dirname)
    
    646 660
                         src_subdir = source_directory.descend(dirname)
    
    661
    +                    print("Now recursing into {} to continue adding {}".format(src_subdir, f))
    
    647 662
                         import_result = dest_subdir._partial_import_cas_into_cas(src_subdir, subcomponents,
    
    648 663
                                                                                  path_prefix=fullname, file_list_required=file_list_required)
    
    649 664
                         result.combine(import_result)
    
    ... ... @@ -651,7 +666,19 @@ class CasBasedDirectory(Directory):
    651 666
                 elif isinstance(source_directory.index[f].buildstream_object, CasBasedDirectory):
    
    652 667
                     # The thing in the input file list is a directory on its own. In which case, replace any existing file, or symlink to file
    
    653 668
                     # with the new, blank directory - if it's neither of those things, or doesn't exist, then just create the dir.
    
    654
    -                self.create_directory(f)
    
    669
    +                if f in self.index:
    
    670
    +                    x = self._resolve(f)
    
    671
    +                    if x is None:
    
    672
    +                        # If we're importing a blank directory, and the target has a broken symlink, then do nothing.
    
    673
    +                        pass
    
    674
    +                    elif isinstance(x, remote_execution_pb2.FileNode):
    
    675
    +                        # Files with the same name, or symlinks to files, get removed.
    
    676
    +                        pass
    
    677
    +                    else:
    
    678
    +                        # There's either a symlink (valid or not) or existing directory with this name, so do nothing.
    
    679
    +                        pass
    
    680
    +                else:
    
    681
    +                    self.create_directory(f)                    
    
    655 682
                 else:
    
    656 683
                     # We're importing a file or symlink - replace anything with the same name.
    
    657 684
                     print("Import of file/symlink {} into this directory. Removing anything existing...".format(f))
    
    ... ... @@ -736,18 +763,22 @@ class CasBasedDirectory(Directory):
    736 763
         def showdiff(self, other):
    
    737 764
             print("Diffing {} and {}:".format(self, other))
    
    738 765
     
    
    739
    -        def compare_list(l1, l2):
    
    766
    +        def compare_list(l1, l2, name):
    
    740 767
                 item2 = None
    
    741 768
                 index = 0
    
    742
    -            print("Comparing lists: {} vs {}".format([d.name for d in l1], [d.name for d in l2]))
    
    769
    +            print("Comparing {} lists: {} vs {}".format(name, [d.name for d in l1], [d.name for d in l2]))
    
    743 770
                 for item1 in l1:
    
    744 771
                     if index>=len(l2):
    
    745 772
                         print("l2 is short: no item to correspond to '{}' in l1.".format(item1.name))
    
    746 773
                         return False
    
    747 774
                     item2 = l2[index]
    
    748 775
                     if item1.name != item2.name:
    
    749
    -                    print("Items do not match: {}, a {} in l1, vs {}, a {} in l2".format(item1.name, self._describe(item1), item2.name, self._describe(item2)))
    
    776
    +                    print("Items do not match in {} list: {}, a {} in l1, vs {}, a {} in l2".format(name, item1.name, self._describe(item1), item2.name, self._describe(item2)))
    
    750 777
                         return False
    
    778
    +                if isinstance(item1, remote_execution_pb2.FileNode):
    
    779
    +                    if item1.is_executable != item2.is_executable:
    
    780
    +                        print("Executable flags do not match on file {}.".format(item1.name))
    
    781
    +                        return False
    
    751 782
                     index += 1
    
    752 783
                 if index != len(l2):
    
    753 784
                     print("l2 is long: Has extra items {}".format(l2[index:]))
    
    ... ... @@ -755,17 +786,19 @@ class CasBasedDirectory(Directory):
    755 786
                 return True
    
    756 787
     
    
    757 788
             def compare_pb2_directories(d1, d2):
    
    758
    -            result = (compare_list(d1.directories, d2.directories)
    
    759
    -                    and compare_list(d1.symlinks, d2.symlinks)
    
    760
    -                    and compare_list(d1.files, d2.files))
    
    789
    +            result = (compare_list(d1.directories, d2.directories, "directory")
    
    790
    +                    and compare_list(d1.symlinks, d2.symlinks, "symlink")
    
    791
    +                    and compare_list(d1.files, d2.files, "file"))
    
    761 792
                 return result
    
    762 793
                             
    
    763 794
             if not compare_pb2_directories(self.pb2_directory, other.pb2_directory):
    
    764 795
                 return False
    
    765 796
     
    
    766 797
             for d in self.pb2_directory.directories:
    
    767
    -            self.index[d.name].buildstream_object.showdiff(other.index[d.name].buildstream_object)
    
    798
    +            if not self.index[d.name].buildstream_object.showdiff(other.index[d.name].buildstream_object):
    
    799
    +                return False
    
    768 800
             print("No differences found in {}".format(self))
    
    801
    +        return True
    
    769 802
                   
    
    770 803
         def show_files_recursive(self):
    
    771 804
             elems = []
    
    ... ... @@ -829,7 +862,8 @@ class CasBasedDirectory(Directory):
    829 862
                 with tempfile.TemporaryDirectory(prefix="roundtrip") as tmpdir:
    
    830 863
                     external_pathspec.export_files(tmpdir)
    
    831 864
                     if files is None:
    
    832
    -                    files = list_relative_paths(tmpdir)
    
    865
    +                    files = list(list_relative_paths(tmpdir))
    
    866
    +                print("Importing from filesystem: filelist is: {}".format(files))
    
    833 867
                     duplicate_cas._import_files_from_directory(tmpdir, files=files)
    
    834 868
                     duplicate_cas._recalculate_recursing_down()
    
    835 869
                     if duplicate_cas.parent:
    

  • tests/storage/virtual_directory_import.py
    ... ... @@ -24,59 +24,61 @@ root_filesets = [
    24 24
         [('a/b/c/textfile1', 'F', 'This is the replacement textfile 1\n')],
    
    25 25
         [('a/b/d', 'D', '')],
    
    26 26
         [('a/b/c', 'S', '/a/b/d')],
    
    27
    -    [('a/b/d', 'D', ''), ('a/b/c', 'S', '/a/b/d')],
    
    27
    +    [('a/b/d', 'D', ''), ('a/b/c', 'S', '/a/b/d')]
    
    28 28
     ]
    
    29 29
     
    
    30 30
     empty_hash_ref = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
    
    31 31
     RANDOM_SEED = 69105
    
    32 32
     
    
    33 33
     
    
    34
    -def generate_import_roots(directory):
    
    35
    -    for fileset in range(1, len(root_filesets) + 1):
    
    36
    -        rootname = "root{}".format(fileset)
    
    37
    -        rootdir = os.path.join(directory, "content", rootname)
    
    38
    -
    
    39
    -        for (path, typesymbol, content) in root_filesets[fileset - 1]:
    
    40
    -            if typesymbol == 'F':
    
    41
    -                (dirnames, filename) = os.path.split(path)
    
    42
    -                os.makedirs(os.path.join(rootdir, dirnames), exist_ok=True)
    
    43
    -                with open(os.path.join(rootdir, dirnames, filename), "wt") as f:
    
    44
    -                    f.write(content)
    
    45
    -            elif typesymbol == 'D':
    
    46
    -                os.makedirs(os.path.join(rootdir, path), exist_ok=True)
    
    47
    -            elif typesymbol == 'S':
    
    48
    -                (dirnames, filename) = os.path.split(path)
    
    49
    -                os.makedirs(os.path.join(rootdir, dirnames), exist_ok=True)
    
    50
    -                os.symlink(content, os.path.join(rootdir, path))
    
    51
    -
    
    52
    -
    
    53
    -def generate_random_roots(directory):
    
    54
    -    random.seed(RANDOM_SEED)
    
    55
    -    for rootno in range(6,13):
    
    56
    -        rootname = "root{}".format(rootno)
    
    57
    -        rootdir = os.path.join(directory, "content", rootname)
    
    58
    -        things = []
    
    59
    -        locations = ['.']
    
    60
    -        os.makedirs(rootdir)
    
    61
    -        for i in range(0, 100):
    
    62
    -            location = random.choice(locations)
    
    63
    -            thingname = "node{}".format(i)
    
    64
    -            thing = random.choice(['dir', 'link', 'file'])
    
    65
    -            target = os.path.join(rootdir, location, thingname)
    
    66
    -            if thing == 'dir':
    
    67
    -                os.makedirs(target)
    
    68
    -                locations.append(os.path.join(location, thingname))
    
    69
    -            elif thing == 'file':
    
    70
    -                with open(target, "wt") as f:
    
    71
    -                    f.write("This is node {}\n".format(i))
    
    72
    -            elif thing == 'link':
    
    73
    -                # TODO: Make some relative symlinks
    
    74
    -                if random.randint(1, 3) == 1 or len(things) == 0:
    
    75
    -                    os.symlink("/broken", target)
    
    76
    -                else:
    
    77
    -                    os.symlink(random.choice(things), target)
    
    78
    -            things.append(os.path.join(location, thingname))
    
    79
    -            print("Generated {}/{} ".format(rootdir, things[-1]))
    
    34
    +def generate_import_roots(rootno, directory):
    
    35
    +    rootname = "root{}".format(rootno)
    
    36
    +    rootdir = os.path.join(directory, "content", rootname)
    
    37
    +
    
    38
    +    for (path, typesymbol, content) in root_filesets[rootno - 1]:
    
    39
    +        if typesymbol == 'F':
    
    40
    +            (dirnames, filename) = os.path.split(path)
    
    41
    +            os.makedirs(os.path.join(rootdir, dirnames), exist_ok=True)
    
    42
    +            with open(os.path.join(rootdir, dirnames, filename), "wt") as f:
    
    43
    +                f.write(content)
    
    44
    +        elif typesymbol == 'D':
    
    45
    +            os.makedirs(os.path.join(rootdir, path), exist_ok=True)
    
    46
    +        elif typesymbol == 'S':
    
    47
    +            (dirnames, filename) = os.path.split(path)
    
    48
    +            os.makedirs(os.path.join(rootdir, dirnames), exist_ok=True)
    
    49
    +            os.symlink(content, os.path.join(rootdir, path))
    
    50
    +
    
    51
    +
    
    52
    +def generate_random_root(rootno, directory):
    
    53
    +    random.seed(RANDOM_SEED+rootno)
    
    54
    +    rootname = "root{}".format(rootno)
    
    55
    +    rootdir = os.path.join(directory, "content", rootname)
    
    56
    +    things = []
    
    57
    +    locations = ['.']
    
    58
    +    os.makedirs(rootdir)
    
    59
    +    for i in range(0, 100):
    
    60
    +        location = random.choice(locations)
    
    61
    +        thingname = "node{}".format(i)
    
    62
    +        thing = random.choice(['dir', 'link', 'file'])
    
    63
    +        target = os.path.join(rootdir, location, thingname)
    
    64
    +        description = thing
    
    65
    +        if thing == 'dir':
    
    66
    +            os.makedirs(target)
    
    67
    +            locations.append(os.path.join(location, thingname))
    
    68
    +        elif thing == 'file':
    
    69
    +            with open(target, "wt") as f:
    
    70
    +                f.write("This is node {}\n".format(i))
    
    71
    +        elif thing == 'link':
    
    72
    +            # TODO: Make some relative symlinks
    
    73
    +            if random.randint(1, 3) == 1 or len(things) == 0:
    
    74
    +                os.symlink("/broken", target)
    
    75
    +                description = "symlink pointing to /broken"
    
    76
    +            else:
    
    77
    +                symlink_destination = random.choice(things)
    
    78
    +                os.symlink(symlink_destination, target)
    
    79
    +                description = "symlink pointing to {}".format(symlink_destination)
    
    80
    +        things.append(os.path.join(location, thingname))
    
    81
    +        print("Generated {}/{}, a {}".format(rootdir, things[-1], description))
    
    80 82
     
    
    81 83
     
    
    82 84
     def file_contents(path):
    
    ... ... @@ -143,20 +145,21 @@ def directory_not_empty(path):
    143 145
         return os.listdir(path)
    
    144 146
     
    
    145 147
     
    
    146
    -@pytest.mark.parametrize("original,overlay", combinations([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]))
    
    147
    -def test_cas_import(cli, tmpdir, original, overlay):
    
    148
    +def _import_test(tmpdir, original, overlay, generator_function, verify_contents=False):
    
    148 149
         fake_context = FakeContext()
    
    149 150
         fake_context.artifactdir = tmpdir
    
    150 151
         # Create some fake content
    
    151
    -    generate_import_roots(tmpdir)
    
    152
    -    generate_random_roots(tmpdir)
    
    152
    +    generator_function(original, tmpdir)
    
    153
    +    if original != overlay:
    
    154
    +        generator_function(overlay, tmpdir)
    
    155
    +        
    
    153 156
         d = create_new_casdir(original, fake_context, tmpdir)
    
    154 157
         d2 = create_new_casdir(overlay, fake_context, tmpdir)
    
    155 158
         print("Importing dir {} into {}".format(overlay, original))
    
    156 159
         d.import_files(d2)
    
    157 160
         d.export_files(os.path.join(tmpdir, "output"))
    
    158 161
         
    
    159
    -    if overlay < 6:
    
    162
    +    if verify_contents:
    
    160 163
             for item in root_filesets[overlay - 1]:
    
    161 164
                 (path, typename, content) = item
    
    162 165
                 realpath = resolve_symlinks(path, os.path.join(tmpdir, "output"))
    
    ... ... @@ -184,14 +187,19 @@ def test_cas_import(cli, tmpdir, original, overlay):
    184 187
         d3.import_files(d2)
    
    185 188
         assert d.ref.hash == d3.ref.hash
    
    186 189
     
    
    190
    +@pytest.mark.parametrize("original,overlay", combinations(range(1,6)))
    
    191
    +def test_fixed_cas_import(cli, tmpdir, original, overlay):
    
    192
    +    _import_test(tmpdir, original, overlay, generate_import_roots, verify_contents=True)
    
    193
    +
    
    194
    +@pytest.mark.parametrize("original,overlay", combinations(range(1,11)))
    
    195
    +def test_random_cas_import(cli, tmpdir, original, overlay):
    
    196
    +    _import_test(tmpdir, original, overlay, generate_random_root, verify_contents=False)
    
    187 197
     
    
    188
    -@pytest.mark.parametrize("root", [1, 2, 3, 4, 5, 6])
    
    189
    -def test_directory_listing(cli, tmpdir, root):
    
    198
    +def _listing_test(tmpdir, root, generator_function):
    
    190 199
         fake_context = FakeContext()
    
    191 200
         fake_context.artifactdir = tmpdir
    
    192 201
         # Create some fake content
    
    193
    -    generate_import_roots(tmpdir)
    
    194
    -    generate_random_roots(tmpdir)
    
    202
    +    generator_function(root, tmpdir)
    
    195 203
     
    
    196 204
         d = create_new_filedir(root, tmpdir)
    
    197 205
         filelist = list(d.list_relative_paths())
    
    ... ... @@ -204,3 +212,12 @@ def test_directory_listing(cli, tmpdir, root):
    204 212
         print("filelist for root {} via CasBasedDirectory:".format(root))
    
    205 213
         print("{}".format(filelist2))
    
    206 214
         assert filelist == filelist2
    
    215
    +    
    
    216
    +
    
    217
    +@pytest.mark.parametrize("root", range(1,11))
    
    218
    +def test_random_directory_listing(cli, tmpdir, root):
    
    219
    +    _listing_test(tmpdir, root, generate_random_root)
    
    220
    +    
    
    221
    +@pytest.mark.parametrize("root", [1, 2, 3, 4, 5])
    
    222
    +def test_fixed_directory_listing(cli, tmpdir, root):
    
    223
    +    _listing_test(tmpdir, root, generate_import_roots)



  • [Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]