| ... | ... | @@ -1890,13 +1890,27 @@ const UnpackResult = struct { |
| 1890 | 1890 | } |
| 1891 | 1891 | }; |
| 1892 | 1892 | |
| 1893 | | test "tarball with duplicate file names" { |
| 1893 | test "tarball with duplicate paths" { |
| 1894 | // This tarball has duplicate path 'dir1/file1' to simulate case sensitve |
| 1895 | // file system on any file sytstem. |
| 1896 | // |
| 1897 | // duplicate_paths/ |
| 1898 | // duplicate_paths/dir1/ |
| 1899 | // duplicate_paths/dir1/file1 |
| 1900 | // duplicate_paths/dir1/file1 |
| 1901 | // duplicate_paths/build.zig.zon |
| 1902 | // duplicate_paths/src/ |
| 1903 | // duplicate_paths/src/main.zig |
| 1904 | // duplicate_paths/src/root.zig |
| 1905 | // duplicate_paths/build.zig |
| 1906 | // |
| 1907 | |
| 1894 | 1908 | const gpa = std.testing.allocator; |
| 1895 | 1909 | var tmp = std.testing.tmpDir(.{}); |
| 1896 | 1910 | defer tmp.cleanup(); |
| 1897 | 1911 | |
| 1898 | | const tarball_name = "package.tar"; |
| 1899 | | try createTestTarball(tmp.dir, tarball_name, false); |
| 1912 | const tarball_name = "duplicate_paths.tar.gz"; |
| 1913 | try saveEmbedFile(tarball_name, tmp.dir); |
| 1900 | 1914 | const tarball_path = try std.fmt.allocPrint(gpa, "zig-cache/tmp/{s}/{s}", .{ tmp.sub_path, tarball_name }); |
| 1901 | 1915 | defer gpa.free(tarball_path); |
| 1902 | 1916 | |
| ... | ... | @@ -1906,41 +1920,104 @@ test "tarball with duplicate file names" { |
| 1906 | 1920 | defer fb.deinit(); |
| 1907 | 1921 | try std.testing.expectError(error.FetchFailed, fetch.run()); |
| 1908 | 1922 | |
| 1909 | | try fb.expectFetchErrors(2, |
| 1923 | try fb.expectFetchErrors(1, |
| 1910 | 1924 | \\error: unable to unpack tarball |
| 1911 | | \\ note: unable to create file 'dir/file': PathAlreadyExists |
| 1912 | 1925 | \\ note: unable to create file 'dir1/file1': PathAlreadyExists |
| 1913 | 1926 | \\ |
| 1914 | 1927 | ); |
| 1915 | 1928 | } |
| 1916 | 1929 | |
| 1917 | | test "tarball with error paths excluded" { |
| 1930 | test "tarball with excluded duplicate paths" { |
| 1931 | // Same as previous tarball but has build.zig.zon wich excludes 'dir1'. |
| 1932 | // |
| 1933 | // .paths = .{ |
| 1934 | // "build.zig", |
| 1935 | // "build.zig.zon", |
| 1936 | // "src", |
| 1937 | // } |
| 1938 | // |
| 1939 | |
| 1918 | 1940 | const gpa = std.testing.allocator; |
| 1919 | 1941 | var tmp = std.testing.tmpDir(.{}); |
| 1920 | 1942 | defer tmp.cleanup(); |
| 1921 | 1943 | |
| 1922 | | const tarball_name = "package.tar"; |
| 1923 | | try createTestTarball(tmp.dir, tarball_name, true); |
| 1944 | const tarball_name = "duplicate_paths_excluded.tar.gz"; |
| 1945 | try saveEmbedFile(tarball_name, tmp.dir); |
| 1924 | 1946 | const tarball_path = try std.fmt.allocPrint(gpa, "zig-cache/tmp/{s}/{s}", .{ tmp.sub_path, tarball_name }); |
| 1925 | 1947 | defer gpa.free(tarball_path); |
| 1926 | 1948 | |
| 1927 | 1949 | // Run tarball fetch, should succeed |
| 1928 | 1950 | var fb: TestFetchBuilder = undefined; |
| 1929 | | var fetch = try fb.build(std.testing.allocator, tmp.dir, tarball_path); |
| 1951 | var fetch = try fb.build(gpa, tmp.dir, tarball_path); |
| 1930 | 1952 | defer fb.deinit(); |
| 1931 | 1953 | try fetch.run(); |
| 1932 | 1954 | |
| 1933 | 1955 | const hex_digest = Package.Manifest.hexDigest(fetch.actual_hash); |
| 1934 | | try std.testing.expectEqualStrings("122022afac878639d5ea6fcca14a123e21fd0395c1f2ef2c89017fa71390f73024af", &hex_digest); |
| 1956 | try std.testing.expectEqualStrings( |
| 1957 | "12200bafe035cbb453dd717741b66e9f9d1e6c674069d06121dafa1b2e62eb6b22da", |
| 1958 | &hex_digest, |
| 1959 | ); |
| 1935 | 1960 | |
| 1936 | 1961 | const expected_files: []const []const u8 = &.{ |
| 1937 | 1962 | "build.zig", |
| 1938 | 1963 | "build.zig.zon", |
| 1939 | 1964 | "src/main.zig", |
| 1965 | "src/root.zig", |
| 1940 | 1966 | }; |
| 1941 | 1967 | try fb.expectPackageFiles(expected_files); |
| 1942 | 1968 | } |
| 1943 | 1969 | |
| 1970 | test "tarball without root folder" { |
| 1971 | // Tarball with root folder. Manifest excludes dir1 and dir2. |
| 1972 | // |
| 1973 | // build.zig |
| 1974 | // build.zig.zon |
| 1975 | // dir1/ |
| 1976 | // dir1/file2 |
| 1977 | // dir1/file1 |
| 1978 | // dir2/ |
| 1979 | // dir2/file2 |
| 1980 | // src/ |
| 1981 | // src/main.zig |
| 1982 | // |
| 1983 | |
| 1984 | const gpa = std.testing.allocator; |
| 1985 | var tmp = std.testing.tmpDir(.{}); |
| 1986 | defer tmp.cleanup(); |
| 1987 | |
| 1988 | const tarball_name = "no_root.tar.gz"; |
| 1989 | try saveEmbedFile(tarball_name, tmp.dir); |
| 1990 | const tarball_path = try std.fmt.allocPrint(gpa, "zig-cache/tmp/{s}/{s}", .{ tmp.sub_path, tarball_name }); |
| 1991 | defer gpa.free(tarball_path); |
| 1992 | |
| 1993 | // Run tarball fetch, should succeed |
| 1994 | var fb: TestFetchBuilder = undefined; |
| 1995 | var fetch = try fb.build(gpa, tmp.dir, tarball_path); |
| 1996 | defer fb.deinit(); |
| 1997 | try fetch.run(); |
| 1998 | |
| 1999 | const hex_digest = Package.Manifest.hexDigest(fetch.actual_hash); |
| 2000 | try std.testing.expectEqualStrings( |
| 2001 | "12209f939bfdcb8b501a61bb4a43124dfa1b2848adc60eec1e4624c560357562b793", |
| 2002 | &hex_digest, |
| 2003 | ); |
| 2004 | |
| 2005 | const expected_files: []const []const u8 = &.{ |
| 2006 | "build.zig", |
| 2007 | "build.zig.zon", |
| 2008 | "src/main.zig", |
| 2009 | }; |
| 2010 | try fb.expectPackageFiles(expected_files); |
| 2011 | } |
| 2012 | |
| 2013 | fn saveEmbedFile(comptime tarball_name: []const u8, dir: fs.Dir) !void { |
| 2014 | //const tarball_name = "duplicate_paths_excluded.tar.gz"; |
| 2015 | const tarball_content = @embedFile("Fetch/testdata/" ++ tarball_name); |
| 2016 | var tmp_file = try dir.createFile(tarball_name, .{}); |
| 2017 | defer tmp_file.close(); |
| 2018 | try tmp_file.writeAll(tarball_content); |
| 2019 | } |
| 2020 | |
| 1944 | 2021 | // Builds Fetch with required dependencies, clears dependencies on deinit(). |
| 1945 | 2022 | const TestFetchBuilder = struct { |
| 1946 | 2023 | thread_pool: ThreadPool, |
| ... | ... | @@ -1981,7 +2058,7 @@ const TestFetchBuilder = struct { |
| 1981 | 2058 | .hash_tok = 0, |
| 1982 | 2059 | .name_tok = 0, |
| 1983 | 2060 | .lazy_status = .eager, |
| 1984 | | .parent_package_root = Cache.Path{ .root_dir = undefined }, |
| 2061 | .parent_package_root = Cache.Path{ .root_dir = Cache.Directory{ .handle = cache_dir, .path = null } }, |
| 1985 | 2062 | .parent_manifest_ast = null, |
| 1986 | 2063 | .prog_node = self.progress.start("Fetch", 0), |
| 1987 | 2064 | .job_queue = &self.job_queue, |
| ... | ... | @@ -2061,66 +2138,3 @@ const TestFetchBuilder = struct { |
| 2061 | 2138 | try std.testing.expectEqualStrings(msg, al.items); |
| 2062 | 2139 | } |
| 2063 | 2140 | }; |
| 2064 | | |
| 2065 | | // Creates tarball with duplicate files names. Simulating case collisions on |
| 2066 | | // case insensitive file system without use of that kind of the file system. |
| 2067 | | // Manifest will exclude those files, so adding manifest should remove duplicate |
| 2068 | | // files problem. |
| 2069 | | fn createTestTarball(dir: fs.Dir, tarball_name: []const u8, with_manifest: bool) !void { |
| 2070 | | const file = try dir.createFile(tarball_name, .{}); |
| 2071 | | defer file.close(); |
| 2072 | | |
| 2073 | | const TarHeader = std.tar.output.Header; |
| 2074 | | const prefix = tarball_name; |
| 2075 | | |
| 2076 | | // add root directory |
| 2077 | | { |
| 2078 | | var hdr = TarHeader.init(); |
| 2079 | | hdr.typeflag = .directory; |
| 2080 | | try hdr.setPath(prefix, ""); |
| 2081 | | try hdr.updateChecksum(); |
| 2082 | | try file.writeAll(std.mem.asBytes(&hdr)); |
| 2083 | | } |
| 2084 | | |
| 2085 | | // add files |
| 2086 | | const files: []const []const u8 = &.{ |
| 2087 | | "build.zig", |
| 2088 | | "src/main.zig", |
| 2089 | | // duplicate file paths |
| 2090 | | "dir/file", |
| 2091 | | "dir1/file1", |
| 2092 | | "dir/file", |
| 2093 | | "dir1/file1", |
| 2094 | | }; |
| 2095 | | |
| 2096 | | for (files) |path| { |
| 2097 | | var hdr = TarHeader.init(); |
| 2098 | | hdr.typeflag = .regular; |
| 2099 | | try hdr.setPath(prefix, path); |
| 2100 | | try hdr.updateChecksum(); |
| 2101 | | try file.writeAll(std.mem.asBytes(&hdr)); |
| 2102 | | } |
| 2103 | | |
| 2104 | | // add manifest |
| 2105 | | if (with_manifest) { |
| 2106 | | const build_zig_zon = |
| 2107 | | \\ .{ |
| 2108 | | \\ .name = "fetch", |
| 2109 | | \\ .version = "0.0.0", |
| 2110 | | \\ .paths = .{ |
| 2111 | | \\ "src", |
| 2112 | | \\ "build.zig", |
| 2113 | | \\ "build.zig.zon" |
| 2114 | | \\ }, |
| 2115 | | \\ } |
| 2116 | | ; |
| 2117 | | var hdr = TarHeader.init(); |
| 2118 | | hdr.typeflag = .regular; |
| 2119 | | try hdr.setPath(prefix, "build.zig.zon"); |
| 2120 | | try hdr.setSize(build_zig_zon.len); |
| 2121 | | try hdr.updateChecksum(); |
| 2122 | | try file.writeAll(std.mem.asBytes(&hdr)); |
| 2123 | | try file.writeAll(build_zig_zon); |
| 2124 | | try file.writeAll(&[_]u8{0} ** (512 - build_zig_zon.len)); |
| 2125 | | } |
| 2126 | | } |