diff --git a/Cargo.lock b/Cargo.lock index 46188d1606c..264ec9bdcbc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,6 +154,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24a6904aef64d73cf10ab17ebace7befb918b82164785cb89907993be7f83813" + [[package]] name = "bitmaps" version = "2.1.0" @@ -451,7 +457,7 @@ version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "bitflags", + "bitflags 1.3.2", "textwrap", "unicode-width", ] @@ -473,7 +479,7 @@ checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f" dependencies = [ "anstream", "anstyle", - "bitflags", + "bitflags 1.3.2", "clap_lex", "strsim", "terminal_size", @@ -765,26 +771,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - [[package]] name = "dunce" version = "1.0.3" @@ -920,7 +906,7 @@ checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "windows-sys 0.48.0", ] @@ -1005,7 +991,7 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89511277159354bea13ae1e53e0c9ab85ba1b20d7e91618fa30e6bc5566857fb" dependencies = [ - "bitflags", + "bitflags 1.3.2", "libc", "libgit2-sys", "log", @@ -1028,9 +1014,9 @@ dependencies = [ [[package]] name = "gix" -version = "0.39.0" +version = "0.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dabfac58aecb4a38cdd2568de66eb1f0d968fd6726f5a80cb8bea7944ef10cc0" +checksum = "6bf41b61f7df395284f7a579c0fa1a7e012c5aede655174d4e91299ef1cac643" dependencies = [ "gix-actor", "gix-attributes", @@ -1040,9 +1026,11 @@ dependencies = [ "gix-diff", "gix-discover", "gix-features", + "gix-fs", "gix-glob", "gix-hash", "gix-hashtable", + "gix-ignore", "gix-index", "gix-lock", "gix-mailmap", @@ -1060,6 +1048,7 @@ dependencies = [ "gix-transport", "gix-traverse", "gix-url", + "gix-utils", "gix-validate", "gix-worktree", "log", @@ -1073,9 +1062,9 @@ dependencies = [ [[package]] name = "gix-actor" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc22b0cdc52237667c301dd7cdc6ead8f8f73c9f824e9942c8ebd6b764f6c0bf" +checksum = "848efa0f1210cea8638f95691c82a46f98a74b9e3524f01d4955ebc25a8f84f3" dependencies = [ "bstr", "btoi", @@ -1087,24 +1076,26 @@ dependencies = [ [[package]] name = "gix-attributes" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2231a25934a240d0a4b6f4478401c73ee81d8be52de0293eedbc172334abf3e1" +checksum = "3015baa01ad2122fbcaab7863c857a603eb7b7ec12ac8141207c42c6439805e2" dependencies = [ "bstr", - "gix-features", "gix-glob", "gix-path", "gix-quote", + "kstring", + "log", + "smallvec", "thiserror", "unicode-bom", ] [[package]] name = "gix-bitmap" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "024bca0c7187517bda5ea24ab148c9ca8208dd0c3e2bea88cdb2008f91791a6d" +checksum = "55a95f4942360766c3880bdb2b4b57f1ef73b190fc424755e7fdf480430af618" dependencies = [ "thiserror", ] @@ -1129,9 +1120,9 @@ dependencies = [ [[package]] name = "gix-config" -version = "0.18.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52c62e26ce11f607712e4f49a0a192ed87675d30187fd61be070abbd607d12f1" +checksum = "1d252a0eddb6df74600d3d8872dc9fe98835a7da43110411d705b682f49d4ac1" dependencies = [ "bstr", "gix-config-value", @@ -1140,6 +1131,7 @@ dependencies = [ "gix-path", "gix-ref", "gix-sec", + "log", "memchr", "nom", "once_cell", @@ -1150,11 +1142,11 @@ dependencies = [ [[package]] name = "gix-config-value" -version = "0.10.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d09154c0c8677e4da0ec35e896f56ee3e338e741b9599fae06075edd83a4081c" +checksum = "786861e84a5793ad5f863d846de5eb064cd23b87e61ad708c8c402608202e7be" dependencies = [ - "bitflags", + "bitflags 2.2.1", "bstr", "gix-path", "libc", @@ -1163,9 +1155,9 @@ dependencies = [ [[package]] name = "gix-credentials" -version = "0.11.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be32b5fe339a31b8e53fa854081dc914c45020dcb64637f3c21baf69c96fc1b" +checksum = "4874a4fc11ffa844a3c2b87a66957bda30a73b577ef1acf15ac34df5745de5ff" dependencies = [ "bstr", "gix-command", @@ -1179,9 +1171,9 @@ dependencies = [ [[package]] name = "gix-date" -version = "0.4.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96271912ce39822501616f177dea7218784e6c63be90d5f36322ff3a722aae2" +checksum = "99056f37270715f5c7584fd8b46899a2296af9cae92463bf58b8bd1f5a78e553" dependencies = [ "bstr", "itoa 1.0.6", @@ -1191,9 +1183,9 @@ dependencies = [ [[package]] name = "gix-diff" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "103a0fa79b0d438f5ecb662502f052e530ace4fe1fe8e1c83c0c6da76d728e67" +checksum = "644a0f2768bc42d7a69289ada80c9e15c589caefc6a315d2307202df83ed1186" dependencies = [ "gix-hash", "gix-object", @@ -1203,9 +1195,9 @@ dependencies = [ [[package]] name = "gix-discover" -version = "0.15.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91c204adba5ebd211c74735cbb65817d277e154486bac0dffa3701f163b80350" +checksum = "5012710ebdecf6193c6866d6409a3b702a4aa0d78c605bc343590b44ab9962a1" dependencies = [ "bstr", "dunce", @@ -1218,9 +1210,9 @@ dependencies = [ [[package]] name = "gix-features" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b76f9a80f6dd7be66442ae86e1f534effad9546676a392acc95e269d0c21c22" +checksum = "cf69b0f5c701cc3ae22d3204b671907668f6437ca88862d355eaf9bc47a4f897" dependencies = [ "bytes", "crc32fast", @@ -1236,21 +1228,32 @@ dependencies = [ "walkdir", ] +[[package]] +name = "gix-fs" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b37a1832f691fdc09910bd267f9a2e413737c1f9ec68c6e31f9e802616278a9" +dependencies = [ + "gix-features", +] + [[package]] name = "gix-glob" -version = "0.5.5" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93e43efd776bc543f46f0fd0ca3d920c37af71a764a16f2aebd89765e9ff2993" +checksum = "c07c98204529ac3f24b34754540a852593d2a4c7349008df389240266627a72a" dependencies = [ - "bitflags", + "bitflags 2.2.1", "bstr", + "gix-features", + "gix-path", ] [[package]] name = "gix-hash" -version = "0.10.4" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a258595457bc192d1f1c59d0d168a1e34e2be9b97a614e14995416185de41a7" +checksum = "078eec3ac2808cc03f0bddd2704cb661da5c5dc33b41a9d7947b141d499c7c42" dependencies = [ "hex", "thiserror", @@ -1258,22 +1261,34 @@ dependencies = [ [[package]] name = "gix-hashtable" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e55e40dfd694884f0eb78796c5bddcf2f8b295dace47039099dd7e76534973" +checksum = "afebb85691c6a085b114e01a27f4a61364519298c5826cb87a45c304802299bc" dependencies = [ "gix-hash", "hashbrown 0.13.2", "parking_lot", ] +[[package]] +name = "gix-ignore" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba205b6df563e2906768bb22834c82eb46c5fdfcd86ba2c347270bc8309a05b2" +dependencies = [ + "bstr", + "gix-glob", + "gix-path", + "unicode-bom", +] + [[package]] name = "gix-index" -version = "0.14.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c12caf7886c7ba06f2b28835cdc2be1dca86bd047d00299d2d49e707ce1c2616" +checksum = "fa282756760f79c401d4f4f42588fbb4aa27bbb4b0830f3b4d3480c21a4ac5a7" dependencies = [ - "bitflags", + "bitflags 2.2.1", "bstr", "btoi", "filetime", @@ -1291,9 +1306,9 @@ dependencies = [ [[package]] name = "gix-lock" -version = "4.0.0" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66119ff8a4a395d0ea033fef718bc85f8b4f0855874f4ce1e005fc16cfe1f66e" +checksum = "41b80172055c5d8017a48ddac5cc7a95421c00211047db0165c97853c4f05194" dependencies = [ "fastrand", "gix-tempfile", @@ -1302,9 +1317,9 @@ dependencies = [ [[package]] name = "gix-mailmap" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b66aea5e52875cd4915f4957a6f4b75831a36981e2ec3f5fad9e370e444fe1a" +checksum = "e8856cec3bdc3610c06970d28b6cb20a0c6621621cf9a8ec48cbd23f2630f362" dependencies = [ "bstr", "gix-actor", @@ -1313,9 +1328,9 @@ dependencies = [ [[package]] name = "gix-object" -version = "0.28.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df068db9180ee935fbb70504848369e270bdcb576b05c0faa8b9fd3b86fc017" +checksum = "c9bb30ce0818d37096daa29efe361a4bc6dd0b51a5726598898be7e9a40a01e1" dependencies = [ "bstr", "btoi", @@ -1332,9 +1347,9 @@ dependencies = [ [[package]] name = "gix-odb" -version = "0.42.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9a5f9e1afbd509761977a2ea02869cedaaba500b4e783deb2e4de5179a55a80" +checksum = "bca2f324aa67672b6d0f2c0fa93f96eb6a7029d260e4c1df5dce3c015f5e5add" dependencies = [ "arc-swap", "gix-features", @@ -1350,9 +1365,9 @@ dependencies = [ [[package]] name = "gix-pack" -version = "0.32.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51db84e1459a8022e518d40a8778028d793dbb28e4d35c9a5eaf92658fb0775" +checksum = "164a515900a83257ae4aa80e741655bee7a2e39113fb535d7a5ac623b445ff20" dependencies = [ "clru", "gix-chunk", @@ -1372,9 +1387,9 @@ dependencies = [ [[package]] name = "gix-packetline" -version = "0.14.3" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d63e5e5a9a92d4fc6b63ff9d94954d25c779ce25c98d5bbe2e4399aa42f7073c" +checksum = "51f53abaf1171d2fe99f80ac8ed6645904a1bfd706674749ac112bdd2d4f0777" dependencies = [ "bstr", "hex", @@ -1383,32 +1398,34 @@ dependencies = [ [[package]] name = "gix-path" -version = "0.7.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32370dce200bb951df013e03dff35b4233fc7a89458642b047629b91734a7e19" +checksum = "4fc78f47095a0c15aea0e66103838f0748f4494bf7a9555dfe0f00425400396c" dependencies = [ "bstr", + "home 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell", "thiserror", ] [[package]] name = "gix-prompt" -version = "0.3.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3034d4d935aef2c7bf719aaa54b88c520e82413118d886ae880a31d5bdee57" +checksum = "330d11fdf88fff3366c2491efde2f3e454958efe7d5ddf60272e8fb1d944bb01" dependencies = [ "gix-command", "gix-config-value", - "nix", "parking_lot", + "rustix", "thiserror", ] [[package]] name = "gix-protocol" -version = "0.28.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d372ab11d5d28ac21800e3f1a6603a67c1ead57f6f5fab07e1e73e960f331c1" +checksum = "877e49417f1730f4dbc2f7d9a2ab0f8b2f49ef08f97270691403ecde3d961e3a" dependencies = [ "bstr", "btoi", @@ -1434,12 +1451,13 @@ dependencies = [ [[package]] name = "gix-ref" -version = "0.26.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90a0ed29e581f04b904ecd0c32b11f33b8209b5a0af9c43f415249a4f2fba632" +checksum = "b8212ecfe41815a2f1b059d82171d6276758cfac5506a5e0f04ad45ef0b1924a" dependencies = [ "gix-actor", "gix-features", + "gix-fs", "gix-hash", "gix-lock", "gix-object", @@ -1453,9 +1471,9 @@ dependencies = [ [[package]] name = "gix-refspec" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aba332462bda2e8efeae4302b39a6ed01ad56ef772fd5b7ef197cf2798294d65" +checksum = "0a6ea733820df67e4cd7797deb12727905824d8f5b7c59d943c456d314475892" dependencies = [ "bstr", "gix-hash", @@ -1467,9 +1485,9 @@ dependencies = [ [[package]] name = "gix-revision" -version = "0.12.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c6f6ff53f888858afc24bf12628446a14279ceec148df6194481f306f553ad2" +checksum = "810f35e9afeccca999d5d348b239f9c162353127d2e13ff3240e31b919e35476" dependencies = [ "bstr", "gix-date", @@ -1481,12 +1499,11 @@ dependencies = [ [[package]] name = "gix-sec" -version = "0.6.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ffa5bf0772f9b01de501c035b6b084cf9b8bb07dec41e3afc6a17336a65f47" +checksum = "794520043d5a024dfeac335c6e520cb616f6963e30dab995892382e998c12897" dependencies = [ - "bitflags", - "dirs", + "bitflags 2.2.1", "gix-path", "libc", "windows", @@ -1494,9 +1511,9 @@ dependencies = [ [[package]] name = "gix-tempfile" -version = "4.1.1" +version = "5.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88751f247234b1f73c8e8056fd835a0999b04e596e052302cb71186005dc4b27" +checksum = "c2ceb30a610e3f5f2d5f9a5114689fde507ba9417705a8cf3429604275b2153c" dependencies = [ "libc", "once_cell", @@ -1508,9 +1525,9 @@ dependencies = [ [[package]] name = "gix-transport" -version = "0.27.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d633947b36a2fbbc089195bdc71621158f1660c2ff2a6b12b0279c16e2f764bc" +checksum = "f01c2bf7b989c679695ef635fc7d9e80072e08101be4b53193c8e8b649900102" dependencies = [ "base64", "bstr", @@ -1527,9 +1544,9 @@ dependencies = [ [[package]] name = "gix-traverse" -version = "0.24.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd9a4a07bb22168dc79c60e1a6a41919d198187ca83d8a5940ad8d7122a45df3" +checksum = "a5be1e807f288c33bb005075111886cceb43ed8a167b3182a0f62c186e2a0dd1" dependencies = [ "gix-hash", "gix-hashtable", @@ -1539,9 +1556,9 @@ dependencies = [ [[package]] name = "gix-url" -version = "0.15.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "044072b7ce8601b62dcec841b92129f5cc677072823324121b395d766ac5f528" +checksum = "dfc77f89054297cc81491e31f1bab4027e554b5ef742a44bd7035db9a0f78b76" dependencies = [ "bstr", "gix-features", @@ -1551,6 +1568,15 @@ dependencies = [ "url", ] +[[package]] +name = "gix-utils" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c10b69beac219acb8df673187a1f07dde2d74092f974fb3f9eb385aeb667c909" +dependencies = [ + "fastrand", +] + [[package]] name = "gix-validate" version = "0.7.4" @@ -1563,15 +1589,18 @@ dependencies = [ [[package]] name = "gix-worktree" -version = "0.14.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cb9af6e56152953d8fe113c4f9d7cf60cf7a982362711e9200a255579b49cb" +checksum = "10bf56a1f5037d84293ea6cece61d9f27c4866b1e13c1c95f37cf56b7da7af25" dependencies = [ "bstr", + "filetime", "gix-attributes", "gix-features", + "gix-fs", "gix-glob", "gix-hash", + "gix-ignore", "gix-index", "gix-object", "gix-path", @@ -1872,6 +1901,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kstring" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747" +dependencies = [ + "static_assertions", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1954,9 +1992,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f508063cc7bb32987c71511216bd5a32be15bccb6a80b52df8b9d7f01fc3aa2" +checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf" [[package]] name = "lock_api" @@ -2049,18 +2087,6 @@ dependencies = [ "windows-sys 0.42.0", ] -[[package]] -name = "nix" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" -dependencies = [ - "bitflags", - "cfg-if", - "libc", - "static_assertions", -] - [[package]] name = "nom" version = "7.1.3" @@ -2134,7 +2160,7 @@ version = "0.10.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e30d8bc91859781f0a943411186324d580f2bbeb71b452fe91ae344806af3f1" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "foreign-types", "libc", @@ -2252,7 +2278,7 @@ checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "smallvec", "windows-sys 0.45.0", ] @@ -2469,7 +2495,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29f1b898011ce9595050a68e60f90bad083ff2987a695a42357134c8381fba70" dependencies = [ "bit-set", - "bitflags", + "bitflags 1.3.2", "byteorder", "lazy_static", "num-traits", @@ -2489,7 +2515,7 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63" dependencies = [ - "bitflags", + "bitflags 1.3.2", "memchr", "unicase", ] @@ -2591,18 +2617,16 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] -name = "redox_users" -version = "0.4.3" +name = "redox_syscall" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "getrandom", - "redox_syscall", - "thiserror", + "bitflags 1.3.2", ] [[package]] @@ -2628,15 +2652,6 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - [[package]] name = "resolver-tests" version = "0.0.0" @@ -2679,11 +2694,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.11" +version = "0.37.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" +checksum = "a0661814f891c57c930a610266415528da53c4933e6dea5fb350cbfe048a9ece" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", @@ -2753,7 +2768,7 @@ version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -3060,16 +3075,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.3.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" dependencies = [ "cfg-if", "fastrand", - "libc", - "redox_syscall", - "remove_dir_all", - "winapi", + "redox_syscall 0.3.5", + "rustix", + "windows-sys 0.45.0", ] [[package]] @@ -3253,9 +3267,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-bom" -version = "1.1.4" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63ec69f541d875b783ca40184d655f2927c95f0bffd486faa83cd3ac3529ec32" +checksum = "98e90c70c9f0d4d1ee6d0a7d04aa06cb9bbd53d8cfbdd62a0269a7c2eb640552" [[package]] name = "unicode-ident" @@ -3543,17 +3557,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.43.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets 0.48.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b16a062fd69..5f988d8ecdf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,8 +42,8 @@ filetime = "0.2.9" flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] } git2 = "0.17.0" git2-curl = "0.18.0" -gix = { version = "0.39.0", default-features = false, features = ["blocking-http-transport-curl", "progress-tree"] } -gix-features-for-configuration-only = { version = "0.28.0", package = "gix-features", features = [ "parallel" ] } +gix = { version = "0.44.1", default-features = false, features = ["blocking-http-transport-curl", "progress-tree"] } +gix-features-for-configuration-only = { version = "0.29.0", package = "gix-features", features = [ "parallel" ] } glob = "0.3.0" hex = "0.4" hmac = "0.12.1" diff --git a/src/cargo/sources/git/mod.rs b/src/cargo/sources/git/mod.rs index 6c230be937b..47827f267cf 100644 --- a/src/cargo/sources/git/mod.rs +++ b/src/cargo/sources/git/mod.rs @@ -6,5 +6,46 @@ mod source; mod utils; pub mod fetch { + use crate::core::features::GitoxideFeatures; + use crate::Config; + + /// The kind remote repository to fetch. + #[derive(Debug, Copy, Clone)] + pub enum RemoteKind { + /// A repository belongs to a git dependency. + GitDependency, + /// A repository belongs to a Cargo registry. + Registry, + } + + impl RemoteKind { + /// Obtain the kind of history we would want for a fetch from our remote knowing if the target repo is already shallow + /// via `repo_is_shallow` along with gitoxide-specific feature configuration via `config`. + /// `rev_and_ref` is additional information that affects whether or not we may be shallow. + pub(crate) fn to_shallow_setting( + &self, + repo_is_shallow: bool, + config: &Config, + ) -> gix::remote::fetch::Shallow { + let has_feature = |cb: &dyn Fn(GitoxideFeatures) -> bool| { + config + .cli_unstable() + .gitoxide + .map_or(false, |features| cb(features)) + }; + + // maintain shallow-ness and keep downloading single commits, or see if we can do shallow clones + if !repo_is_shallow { + match self { + RemoteKind::GitDependency if has_feature(&|git| git.shallow_deps) => {} + RemoteKind::Registry if has_feature(&|git| git.shallow_index) => {} + _ => return gix::remote::fetch::Shallow::NoChange, + } + }; + + gix::remote::fetch::Shallow::DepthAtRemote(1.try_into().expect("non-zero")) + } + } + pub type Error = gix::env::collate::fetch::Error; } diff --git a/src/cargo/sources/git/oxide.rs b/src/cargo/sources/git/oxide.rs index 0270579da75..c8d0a4ecd38 100644 --- a/src/cargo/sources/git/oxide.rs +++ b/src/cargo/sources/git/oxide.rs @@ -29,6 +29,10 @@ pub fn with_retry_and_progress( ) -> CargoResult<()> { std::thread::scope(|s| { let mut progress_bar = Progress::new("Fetch", config); + let is_shallow = config + .cli_unstable() + .gitoxide + .map_or(false, |gix| gix.shallow_deps || gix.shallow_index); network::retry::with_retry(config, || { let progress_root: Arc = gix::progress::tree::root::Options { @@ -50,7 +54,7 @@ pub fn with_retry_and_progress( ); amend_authentication_hints(res, urls.get_mut().take()) }); - translate_progress_to_bar(&mut progress_bar, root)?; + translate_progress_to_bar(&mut progress_bar, root, is_shallow)?; thread.join().expect("no panic in scoped thread") }) }) @@ -59,7 +63,9 @@ pub fn with_retry_and_progress( fn translate_progress_to_bar( progress_bar: &mut Progress<'_>, root: Weak, + is_shallow: bool, ) -> CargoResult<()> { + let remote_progress: gix::progress::Id = gix::remote::fetch::ProgressId::RemoteProgress.into(); let read_pack_bytes: gix::progress::Id = gix::odb::pack::bundle::write::ProgressId::ReadPackBytes.into(); let delta_index_objects: gix::progress::Id = @@ -88,6 +94,7 @@ fn translate_progress_to_bar( "progress should be smoother by keeping these as multiples of each other" ); + let num_phases = if is_shallow { 3 } else { 2 }; // indexing + delta-resolution, both with same amount of objects to handle while let Some(root) = root.upgrade() { std::thread::sleep(sleep_interval); let needs_update = last_fast_update.elapsed() >= fast_check_interval; @@ -102,31 +109,37 @@ fn translate_progress_to_bar( fn progress_by_id( id: gix::progress::Id, task: &gix::progress::Task, - ) -> Option<&gix::progress::Value> { - (task.id == id).then(|| task.progress.as_ref()).flatten() + ) -> Option<(&str, &gix::progress::Value)> { + (task.id == id) + .then(|| task.progress.as_ref()) + .flatten() + .map(|value| (task.name.as_str(), value)) } fn find_in( tasks: &[(K, gix::progress::Task)], - cb: impl Fn(&gix::progress::Task) -> Option<&gix::progress::Value>, - ) -> Option<&gix::progress::Value> { + cb: impl Fn(&gix::progress::Task) -> Option<(&str, &gix::progress::Value)>, + ) -> Option<(&str, &gix::progress::Value)> { tasks.iter().find_map(|(_, t)| cb(t)) } - const NUM_PHASES: usize = 2; // indexing + delta-resolution, both with same amount of objects to handle - if let Some(objs) = find_in(&tasks, |t| progress_by_id(resolve_objects, t)) { - // Resolving deltas. + if let Some((_, objs)) = find_in(&tasks, |t| progress_by_id(resolve_objects, t)) { + // Phase 3: Resolving deltas. let objects = objs.step.load(Ordering::Relaxed); let total_objects = objs.done_at.expect("known amount of objects"); let msg = format!(", ({objects}/{total_objects}) resolving deltas"); - progress_bar.tick(total_objects + objects, total_objects * NUM_PHASES, &msg)?; + progress_bar.tick( + (total_objects * (num_phases - 1)) + objects, + total_objects * num_phases, + &msg, + )?; } else if let Some((objs, read_pack)) = find_in(&tasks, |t| progress_by_id(read_pack_bytes, t)).and_then(|read| { find_in(&tasks, |t| progress_by_id(delta_index_objects, t)) - .map(|delta| (delta, read)) + .map(|delta| (delta.1, read.1)) }) { - // Receiving objects. + // Phase 2: Receiving objects. let objects = objs.step.load(Ordering::Relaxed); let total_objects = objs.done_at.expect("known amount of objects"); let received_bytes = read_pack.step.load(Ordering::Relaxed); @@ -139,7 +152,25 @@ fn translate_progress_to_bar( let (rate, unit) = human_readable_bytes(counter.rate() as u64); let msg = format!(", {rate:.2}{unit}/s"); - progress_bar.tick(objects, total_objects * NUM_PHASES, &msg)?; + progress_bar.tick( + (total_objects * (num_phases - 2)) + objects, + total_objects * num_phases, + &msg, + )?; + } else if let Some((action, remote)) = + find_in(&tasks, |t| progress_by_id(remote_progress, t)) + { + if !is_shallow { + continue; + } + // phase 1: work on the remote side + + // Resolving deltas. + let objects = remote.step.load(Ordering::Relaxed); + if let Some(total_objects) = remote.done_at { + let msg = format!(", ({objects}/{total_objects}) {action}"); + progress_bar.tick(objects, total_objects * num_phases, &msg)?; + } } } Ok(()) @@ -232,7 +263,7 @@ pub fn open_repo( ) -> Result { gix::open_opts(repo_path, { let mut opts = gix::open::Options::default(); - opts.permissions.config = gix::permissions::Config::all(); + opts.permissions.config = gix::open::permissions::Config::all(); opts.permissions.config.git_binary = purpose.needs_git_binary_config(); opts.with(gix::sec::Trust::Full) .config_overrides(config_overrides) diff --git a/src/cargo/sources/git/source.rs b/src/cargo/sources/git/source.rs index 90c47093dce..4cdb8983b9e 100644 --- a/src/cargo/sources/git/source.rs +++ b/src/cargo/sources/git/source.rs @@ -29,17 +29,26 @@ impl<'cfg> GitSource<'cfg> { assert!(source_id.is_git(), "id is not git, id={}", source_id); let remote = GitRemote::new(source_id.url()); - let ident = ident(&source_id); - - let source = GitSource { - remote, - manifest_reference: source_id.git_reference().unwrap().clone(), - locked_rev: match source_id.precise() { + let manifest_reference = source_id.git_reference().unwrap().clone(); + let locked_rev = + match source_id.precise() { Some(s) => Some(git2::Oid::from_str(s).with_context(|| { format!("precise value for git is not a git revision: {}", s) })?), None => None, - }, + }; + let ident = ident_shallow( + &source_id, + config + .cli_unstable() + .gitoxide + .map_or(false, |gix| gix.fetch && gix.shallow_deps), + ); + + let source = GitSource { + remote, + manifest_reference, + locked_rev, source_id, path_source: None, ident, @@ -63,6 +72,7 @@ impl<'cfg> GitSource<'cfg> { } } +/// Create an identifier from a URL, essentially turning `proto://host/path/repo` into `repo-`. fn ident(id: &SourceId) -> String { let ident = id .canonical_url() @@ -76,6 +86,18 @@ fn ident(id: &SourceId) -> String { format!("{}-{}", ident, short_hash(id.canonical_url())) } +/// Like `ident()`, but appends `-shallow` to it, turning `proto://host/path/repo` into `repo--shallow`. +/// +/// It's important to separate shallow from non-shallow clones for reasons of backwards compatibility - older +/// cargo's aren't necessarily handling shallow clones correctly. +fn ident_shallow(id: &SourceId, is_shallow: bool) -> String { + let mut ident = ident(id); + if is_shallow { + ident.push_str("-shallow"); + } + ident +} + impl<'cfg> Debug for GitSource<'cfg> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "git repo at {}", self.remote.url())?; diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs index a7ffccf79a4..c14d1daf3ca 100644 --- a/src/cargo/sources/git/utils.rs +++ b/src/cargo/sources/git/utils.rs @@ -2,6 +2,7 @@ //! authentication/cloning. use crate::core::{GitReference, Verbosity}; +use crate::sources::git::fetch::RemoteKind; use crate::sources::git::oxide; use crate::sources::git::oxide::cargo_config_to_gitoxide_overrides; use crate::util::errors::CargoResult; @@ -96,20 +97,24 @@ impl GitRemote { // if we can. If that can successfully load our revision then we've // populated the database with the latest version of `reference`, so // return that database and the rev we resolve to. + let locked_ref = locked_rev.map(|oid| GitReference::Rev(oid.to_string())); + let reference = locked_ref.as_ref().unwrap_or(reference); if let Some(mut db) = db { - fetch(&mut db.repo, self.url.as_str(), reference, cargo_config) - .context(format!("failed to fetch into: {}", into.display()))?; - match locked_rev { - Some(rev) => { - if db.contains(rev) { - return Ok((db, rev)); - } - } - None => { - if let Ok(rev) = reference.resolve(&db.repo) { - return Ok((db, rev)); - } - } + fetch( + &mut db.repo, + self.url.as_str(), + reference, + cargo_config, + RemoteKind::GitDependency, + ) + .with_context(|| format!("failed to fetch into: {}", into.display()))?; + + let resolved_commit_hash = match locked_rev { + Some(rev) => db.contains(rev).then_some(rev), + None => reference.resolve(&db.repo).ok(), + }; + if let Some(rev) = resolved_commit_hash { + return Ok((db, rev)); } } @@ -121,8 +126,14 @@ impl GitRemote { } paths::create_dir_all(into)?; let mut repo = init(into, true)?; - fetch(&mut repo, self.url.as_str(), reference, cargo_config) - .context(format!("failed to clone into: {}", into.display()))?; + fetch( + &mut repo, + self.url.as_str(), + reference, + cargo_config, + RemoteKind::GitDependency, + ) + .with_context(|| format!("failed to clone into: {}", into.display()))?; let rev = match locked_rev { Some(rev) => rev, None => reference.resolve(&repo)?, @@ -282,6 +293,16 @@ impl<'a> GitCheckout<'a> { .with_checkout(checkout) .fetch_options(fopts) .clone(url.as_str(), into)?; + // `git2` doesn't seem to handle shallow repos correctly when doing a local clone. + // Fortunately all that's needed is the copy of the one file that defines the + // shallow boundary, the commits which have their parents omitted as part of the + // shallow clone. + if database.repo.is_shallow() { + std::fs::copy( + database.repo.path().join("shallow"), + r.path().join("shallow"), + )?; + } repo = Some(r); Ok(()) })?; @@ -432,7 +453,14 @@ impl<'a> GitCheckout<'a> { cargo_config .shell() .status("Updating", format!("git submodule `{}`", url))?; - fetch(&mut repo, &url, &reference, cargo_config).with_context(|| { + fetch( + &mut repo, + &url, + &reference, + cargo_config, + RemoteKind::GitDependency, + ) + .with_context(|| { format!( "failed to fetch submodule `{}` from {}", child.name().unwrap_or(""), @@ -803,11 +831,15 @@ pub fn with_fetch_options( }) } +/// Note that `history` is a complex computed value to determine whether it's acceptable to perform shallow clones +/// at all. It's needed to allow the caller to determine the correct position of the destination repository or move it +/// into place should its position change. pub fn fetch( repo: &mut git2::Repository, orig_url: &str, reference: &GitReference, config: &Config, + remote_kind: RemoteKind, ) -> CargoResult<()> { if config.frozen() { anyhow::bail!( @@ -819,8 +851,10 @@ pub fn fetch( anyhow::bail!("can't update a git repository in the offline mode") } + let shallow = remote_kind.to_shallow_setting(repo.is_shallow(), config); + // If we're fetching from GitHub, attempt GitHub's special fast path for - // testing if we've already got an up-to-date copy of the repository + // testing if we've already got an up-to-date copy of the repository. let oid_to_fetch = match github_fast_path(repo, orig_url, reference, config) { Ok(FastPathRev::UpToDate) => return Ok(()), Ok(FastPathRev::NeedsFetch(rev)) => Some(rev), @@ -852,6 +886,7 @@ pub fn fetch( GitReference::Branch(b) => { refspecs.push(format!("+refs/heads/{0}:refs/remotes/origin/{0}", b)); } + GitReference::Tag(t) => { refspecs.push(format!("+refs/tags/{0}:refs/remotes/origin/tags/{0}", t)); } @@ -865,6 +900,16 @@ pub fn fetch( refspecs.push(format!("+{0}:{0}", rev)); } else if let Some(oid_to_fetch) = oid_to_fetch { refspecs.push(format!("+{0}:refs/commit/{0}", oid_to_fetch)); + } else if !matches!(shallow, gix::remote::fetch::Shallow::NoChange) + && rev.parse::().is_ok() + { + // There is a specific commit to fetch and we will do so in shallow-mode only + // to not disturb the previous logic. + // Note that with typical settings for shallowing, we will just fetch a single `rev` + // as single commit. + // The reason we write to `refs/remotes/origin/HEAD` is that it's of special significance + // when during `GitReference::resolve()`, but otherwise it shouldn't matter. + refspecs.push(format!("+{0}:refs/remotes/origin/HEAD", rev)); } else { // We don't know what the rev will point to. To handle this // situation we fetch all branches and tags, and then we pray @@ -936,8 +981,7 @@ pub fn fetch( .url(gix::remote::Direction::Fetch) .expect("set at init") .to_owned(); - let connection = - remote.connect(gix::remote::Direction::Fetch, &mut progress)?; + let connection = remote.connect(gix::remote::Direction::Fetch)?; let mut authenticate = connection.configured_credentials(url)?; let connection = connection.with_credentials( move |action: gix::protocol::credentials::helper::Action| { @@ -951,8 +995,9 @@ pub fn fetch( }, ); let outcome = connection - .prepare_fetch(gix::remote::ref_map::Options::default())? - .receive(should_interrupt)?; + .prepare_fetch(&mut progress, gix::remote::ref_map::Options::default())? + .with_shallow(shallow.clone().into()) + .receive(&mut progress, should_interrupt)?; Ok(outcome) }); let err = match res { @@ -967,6 +1012,7 @@ pub fn fetch( // folder before writing files into it, or else not even open a directory as git repository (which is // also handled here). && err.is_corrupted() + || has_shallow_lock_file(&err) { repo_reinitialized.store(true, Ordering::Relaxed); debug!( @@ -1036,6 +1082,17 @@ pub fn fetch( } } +/// `gitoxide` uses shallow locks to assure consistency when fetching to and to avoid races, and to write +/// files atomically. +/// Cargo has its own lock files and doesn't need that mechanism for race protection, so a stray lock means +/// a signal interrupted a previous shallow fetch and doesn't mean a race is happening. +fn has_shallow_lock_file(err: &crate::sources::git::fetch::Error) -> bool { + matches!( + err, + gix::env::collate::fetch::Error::Fetch(gix::remote::fetch::Error::LockShallowFile(_)) + ) +} + fn fetch_with_cli( repo: &mut git2::Repository, url: &str, diff --git a/src/cargo/sources/registry/mod.rs b/src/cargo/sources/registry/mod.rs index aa3f5dc5ff4..5a90080ff2b 100644 --- a/src/cargo/sources/registry/mod.rs +++ b/src/cargo/sources/registry/mod.rs @@ -549,10 +549,14 @@ mod index; mod local; mod remote; -fn short_name(id: SourceId) -> String { +fn short_name(id: SourceId, is_shallow: bool) -> String { let hash = hex::short_hash(&id); let ident = id.url().host_str().unwrap_or("").to_string(); - format!("{}-{}", ident, hash) + let mut name = format!("{}-{}", ident, hash); + if is_shallow { + name.push_str("-shallow"); + } + name } impl<'cfg> RegistrySource<'cfg> { @@ -562,7 +566,14 @@ impl<'cfg> RegistrySource<'cfg> { config: &'cfg Config, ) -> CargoResult> { assert!(source_id.is_remote_registry()); - let name = short_name(source_id); + let name = short_name( + source_id, + config + .cli_unstable() + .gitoxide + .map_or(false, |gix| gix.fetch && gix.shallow_index) + && !source_id.is_sparse(), + ); let ops = if source_id.is_sparse() { Box::new(http_remote::HttpRegistry::new(source_id, config, &name)?) as Box<_> } else { @@ -584,7 +595,7 @@ impl<'cfg> RegistrySource<'cfg> { yanked_whitelist: &HashSet, config: &'cfg Config, ) -> RegistrySource<'cfg> { - let name = short_name(source_id); + let name = short_name(source_id, false); let ops = local::LocalRegistry::new(path, config, &name); RegistrySource::new(source_id, config, &name, Box::new(ops), yanked_whitelist) } diff --git a/src/cargo/sources/registry/remote.rs b/src/cargo/sources/registry/remote.rs index 3e502914472..f4df4e86b11 100644 --- a/src/cargo/sources/registry/remote.rs +++ b/src/cargo/sources/registry/remote.rs @@ -1,5 +1,6 @@ use crate::core::{GitReference, PackageId, SourceId}; use crate::sources::git; +use crate::sources::git::fetch::RemoteKind; use crate::sources::registry::download; use crate::sources::registry::MaybeLock; use crate::sources::registry::{LoadResponse, RegistryConfig, RegistryData}; @@ -304,8 +305,14 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> { // checkout. let url = self.source_id.url(); let repo = self.repo.borrow_mut().unwrap(); - git::fetch(repo, url.as_str(), &self.index_git_ref, self.config) - .with_context(|| format!("failed to fetch `{}`", url))?; + git::fetch( + repo, + url.as_str(), + &self.index_git_ref, + self.config, + RemoteKind::Registry, + ) + .with_context(|| format!("failed to fetch `{}`", url))?; // Create a dummy file to record the mtime for when we updated the // index. diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index accd45d8ee8..9dfa0f37e1f 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -1260,10 +1260,20 @@ to run with `gitoxide` with the `-Zgitoxide=operation[,operationN]` syntax. Valid operations are the following: * `fetch` - All fetches are done with `gitoxide`, which includes git dependencies as well as the crates index. -* `shallow-index` *(planned)* - perform a shallow clone of the index. -* `shallow-deps` *(planned)* - perform a shallow clone of git dependencies. +* `shallow-index` - perform a shallow clone of the index. +* `shallow-deps` - perform a shallow clone of git dependencies. * `checkout` *(planned)* - checkout the worktree, with support for filters and submodules. +**Details on shallow clones** + +* To enable shallow clones, add `-Zgitoxide=fetch,shallow_deps` for fetching git dependencies or `-Zgitoxide=fetch,shallow_index` for fetching registry index. +* Shallow-cloned and shallow-checked-out git repositories reside at their own `-shallow` suffixed directories, i.e, + - `~/.cargo/registry/index/*-shallow` + - `~/.cargo/git/db/*-shallow` + - `~/.cargo/git/checkouts/*-shallow` +* When the unstable feature is on, fetching/cloning a git repository is always a shallow fetch. This roughly equals to `git fetch --depth 1` everywhere. +* Even with the presence of `Cargo.lock` or specifying a commit `{ rev = "…" }`, gitoxide is still smart enough to shallow fetch without unshallowing the existing repository. + ## Stabilized and removed features ### Compile progress diff --git a/tests/testsuite/git.rs b/tests/testsuite/git.rs index b170c204f75..32d0730c129 100644 --- a/tests/testsuite/git.rs +++ b/tests/testsuite/git.rs @@ -547,90 +547,6 @@ Caused by: .run(); } -#[cargo_test] -fn two_revs_same_deps() { - let bar = git::new("meta-dep", |project| { - project - .file("Cargo.toml", &basic_manifest("bar", "0.0.0")) - .file("src/lib.rs", "pub fn bar() -> i32 { 1 }") - }); - - let repo = git2::Repository::open(&bar.root()).unwrap(); - let rev1 = repo.revparse_single("HEAD").unwrap().id(); - - // Commit the changes and make sure we trigger a recompile - bar.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }"); - git::add(&repo); - let rev2 = git::commit(&repo); - - let foo = project() - .file( - "Cargo.toml", - &format!( - r#" - [package] - name = "foo" - version = "0.0.0" - authors = [] - - [dependencies.bar] - git = '{}' - rev = "{}" - - [dependencies.baz] - path = "../baz" - "#, - bar.url(), - rev1 - ), - ) - .file( - "src/main.rs", - r#" - extern crate bar; - extern crate baz; - - fn main() { - assert_eq!(bar::bar(), 1); - assert_eq!(baz::baz(), 2); - } - "#, - ) - .build(); - - let _baz = project() - .at("baz") - .file( - "Cargo.toml", - &format!( - r#" - [package] - name = "baz" - version = "0.0.0" - authors = [] - - [dependencies.bar] - git = '{}' - rev = "{}" - "#, - bar.url(), - rev2 - ), - ) - .file( - "src/lib.rs", - r#" - extern crate bar; - pub fn baz() -> i32 { bar::bar() } - "#, - ) - .build(); - - foo.cargo("build -v").run(); - assert!(foo.bin("foo").is_file()); - foo.process(&foo.bin("foo")).run(); -} - #[cargo_test] fn recompilation() { let git_project = git::new("bar", |project| { diff --git a/tests/testsuite/git_shallow.rs b/tests/testsuite/git_shallow.rs new file mode 100644 index 00000000000..8045880cfd4 --- /dev/null +++ b/tests/testsuite/git_shallow.rs @@ -0,0 +1,831 @@ +use crate::git_gc::find_index; +use cargo_test_support::registry::Package; +use cargo_test_support::{basic_manifest, git, paths, project}; + +enum RepoMode { + Shallow, + Complete, +} + +#[cargo_test] +fn gitoxide_clones_shallow_two_revs_same_deps() { + perform_two_revs_same_deps(true) +} + +fn perform_two_revs_same_deps(shallow: bool) { + let bar = git::new("meta-dep", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.0.0")) + .file("src/lib.rs", "pub fn bar() -> i32 { 1 }") + }); + + let repo = git2::Repository::open(&bar.root()).unwrap(); + let rev1 = repo.revparse_single("HEAD").unwrap().id(); + + // Commit the changes and make sure we trigger a recompile + bar.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }"); + git::add(&repo); + let rev2 = git::commit(&repo); + + let foo = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + + [dependencies.bar] + git = '{}' + rev = "{}" + + [dependencies.baz] + path = "../baz" + "#, + bar.url(), + rev1 + ), + ) + .file( + "src/main.rs", + r#" + extern crate bar; + extern crate baz; + + fn main() { + assert_eq!(bar::bar(), 1); + assert_eq!(baz::baz(), 2); + } + "#, + ) + .build(); + + let _baz = project() + .at("baz") + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "baz" + version = "0.0.0" + authors = [] + + [dependencies.bar] + git = '{}' + rev = "{}" + "#, + bar.url(), + rev2 + ), + ) + .file( + "src/lib.rs", + r#" + extern crate bar; + pub fn baz() -> i32 { bar::bar() } + "#, + ) + .build(); + + let args = if shallow { + "build -v -Zgitoxide=fetch,shallow-deps" + } else { + "build -v" + }; + foo.cargo(args) + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + assert!(foo.bin("foo").is_file()); + foo.process(&foo.bin("foo")).run(); +} + +#[cargo_test] +fn two_revs_same_deps() { + perform_two_revs_same_deps(false) +} + +#[cargo_test] +fn gitoxide_clones_registry_with_shallow_protocol_and_follow_up_with_git2_fetch( +) -> anyhow::Result<()> { + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch") + .arg("-Zgitoxide=fetch,shallow-index") + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + let shallow_repo = gix::open_opts(find_index(), gix::open::Options::isolated())?; + assert_eq!( + shallow_repo + .rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "shallow clones always start at depth of 1 to minimize download size" + ); + assert!(shallow_repo.is_shallow()); + + Package::new("bar", "1.1.0").publish(); + p.cargo("update") + .env("__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2", "0") + .run(); + + let repo = gix::open_opts( + find_remote_index(RepoMode::Complete), + gix::open::Options::isolated(), + )?; + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 3, + "an entirely new repo was cloned which is never shallow" + ); + assert!(!repo.is_shallow()); + Ok(()) +} + +#[cargo_test] +fn gitoxide_clones_git_dependency_with_shallow_protocol_and_git2_is_used_for_followup_fetches( +) -> anyhow::Result<()> { + // Example where an old lockfile with an explicit branch="master" in Cargo.toml. + Package::new("bar", "1.0.0").publish(); + let (bar, bar_repo) = git::new_repo("bar", |p| { + p.file("Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("src/lib.rs", "") + }); + + bar.change_file("src/lib.rs", "// change"); + git::add(&bar_repo); + git::commit(&bar_repo); + + { + let mut walk = bar_repo.revwalk()?; + walk.push_head()?; + assert_eq!( + walk.count(), + 2, + "original repo has initial commit and change commit" + ); + } + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = {{ version = "1.0", git = "{}", branch = "master" }} + "#, + bar.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("update") + .arg("-Zgitoxide=fetch,shallow-deps") + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + let db_clone = gix::open_opts( + find_bar_db(RepoMode::Shallow), + gix::open::Options::isolated(), + )?; + assert!(db_clone.is_shallow()); + assert_eq!( + db_clone + .rev_parse_single("origin/master")? + .ancestors() + .all()? + .count(), + 1, + "db clones are shallow and have a shortened history" + ); + + let dep_checkout = gix::open_opts( + find_lexicographically_first_bar_checkout(), + gix::open::Options::isolated(), + )?; + assert!(dep_checkout.is_shallow()); + assert_eq!( + dep_checkout.head_id()?.ancestors().all()?.count(), + 1, + "db checkouts are hard-linked clones with the shallow file copied separately." + ); + + bar.change_file("src/lib.rs", "// another change"); + git::add(&bar_repo); + git::commit(&bar_repo); + { + let mut walk = bar_repo.revwalk()?; + walk.push_head()?; + assert_eq!( + walk.count(), + 3, + "original repo has initial commit and change commit, and another change" + ); + } + + p.cargo("update") + .env("__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2", "0") + .run(); + + let db_clone = gix::open_opts( + find_bar_db(RepoMode::Complete), + gix::open::Options::isolated(), + )?; + assert_eq!( + db_clone + .rev_parse_single("origin/master")? + .ancestors() + .all()? + .count(), + 3, + "the db clone was re-initialized and has all commits" + ); + assert!( + !db_clone.is_shallow(), + "shallow-ness was removed as git2 does not support it" + ); + assert_eq!( + dep_checkout.head_id()?.ancestors().all()?.count(), + 1, + "the original dep checkout didn't change - there is a new one for each update we get locally" + ); + + let max_history_depth = glob::glob( + paths::home() + .join(".cargo/git/checkouts/bar-*/*/.git") + .to_str() + .unwrap(), + )? + .map(|path| -> anyhow::Result { + let dep_checkout = gix::open_opts(path?, gix::open::Options::isolated())?; + let depth = dep_checkout.head_id()?.ancestors().all()?.count(); + assert_eq!(dep_checkout.is_shallow(), depth == 1, "the first checkout is done with gitoxide and shallow, the second one is git2 non-shallow"); + Ok(depth) + }) + .map(Result::unwrap) + .max() + .expect("two checkout repos"); + + assert_eq!( + max_history_depth, 3, + "the new checkout sees all commits of the non-shallow DB repository" + ); + + Ok(()) +} + +#[cargo_test] +fn gitoxide_shallow_clone_followed_by_non_shallow_update() -> anyhow::Result<()> { + Package::new("bar", "1.0.0").publish(); + let (bar, bar_repo) = git::new_repo("bar", |p| { + p.file("Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("src/lib.rs", "") + }); + + bar.change_file("src/lib.rs", "// change"); + git::add(&bar_repo); + git::commit(&bar_repo); + + { + let mut walk = bar_repo.revwalk()?; + walk.push_head()?; + assert_eq!( + walk.count(), + 2, + "original repo has initial commit and change commit" + ); + } + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = {{ version = "1.0", git = "{}", branch = "master" }} + "#, + bar.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("update") + .arg("-Zgitoxide=fetch,shallow-deps") + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + let shallow_db_clone = gix::open_opts( + find_bar_db(RepoMode::Shallow), + gix::open::Options::isolated(), + )?; + assert!(shallow_db_clone.is_shallow()); + assert_eq!( + shallow_db_clone + .rev_parse_single("origin/master")? + .ancestors() + .all()? + .count(), + 1, + "db clones are shallow and have a shortened history" + ); + + let dep_checkout = gix::open_opts( + find_lexicographically_first_bar_checkout(), + gix::open::Options::isolated(), + )?; + assert!(dep_checkout.is_shallow()); + assert_eq!( + dep_checkout.head_id()?.ancestors().all()?.count(), + 1, + "db checkouts are hard-linked clones with the shallow file copied separately." + ); + + bar.change_file("src/lib.rs", "// another change"); + git::add(&bar_repo); + git::commit(&bar_repo); + { + let mut walk = bar_repo.revwalk()?; + walk.push_head()?; + assert_eq!( + walk.count(), + 3, + "original repo has initial commit and change commit, and another change" + ); + } + + p.cargo("update") + .arg("-Zgitoxide=fetch") // shallow-deps is omitted intentionally + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + let db_clone = gix::open_opts( + find_bar_db(RepoMode::Complete), + gix::open::Options::isolated(), + )?; + assert_eq!( + db_clone + .rev_parse_single("origin/master")? + .ancestors() + .all()? + .count(), + 3, + "we created an entirely new non-shallow clone" + ); + assert!(!db_clone.is_shallow()); + assert_eq!( + dep_checkout.head_id()?.ancestors().all()?.count(), + 1, + "the original dep checkout didn't change - there is a new one for each update we get locally" + ); + + let max_history_depth = glob::glob( + paths::home() + .join(".cargo/git/checkouts/bar-*/*/.git") + .to_str() + .unwrap(), + )? + .map(|path| -> anyhow::Result { + let path = path?; + let dep_checkout = gix::open_opts(&path, gix::open::Options::isolated())?; + assert_eq!( + dep_checkout.is_shallow(), + path.to_string_lossy().contains("-shallow"), + "checkouts of shallow db repos are shallow as well" + ); + let depth = dep_checkout.head_id()?.ancestors().all()?.count(); + Ok(depth) + }) + .map(Result::unwrap) + .max() + .expect("two checkout repos"); + + assert_eq!( + max_history_depth, 3, + "we see the previous shallow checkout as well as new new unshallow one" + ); + + Ok(()) +} + +#[cargo_test] +fn gitoxide_clones_registry_with_shallow_protocol_and_follow_up_fetch_maintains_shallowness( +) -> anyhow::Result<()> { + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch") + .arg("-Zgitoxide=fetch,shallow-index") + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + let repo = gix::open_opts(find_index(), gix::open::Options::isolated())?; + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "shallow clones always start at depth of 1 to minimize download size" + ); + assert!(repo.is_shallow()); + + Package::new("bar", "1.1.0").publish(); + p.cargo("update") + .arg("-Zgitoxide=fetch,shallow-index") // NOTE: the flag needs to be consistent or else a different index is created + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "subsequent shallow fetches wont' fetch what's inbetween, only the single commit that we need while leveraging existing commits" + ); + assert!(repo.is_shallow()); + + Package::new("bar", "1.2.0").publish(); + Package::new("bar", "1.3.0").publish(); + p.cargo("update") + .arg("-Zgitoxide=fetch,shallow-index") + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "shallow boundaries are moved with each fetch to maintain only a single commit of history" + ); + assert!(repo.is_shallow()); + + Ok(()) +} + +/// If there is shallow *and* non-shallow clones, non-shallow will naturally be returned due to sort order. +#[cargo_test] +fn gitoxide_clones_registry_without_shallow_protocol_and_follow_up_fetch_uses_shallowness( +) -> anyhow::Result<()> { + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch") + .arg("-Zgitoxide=fetch") + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + let repo = gix::open_opts(find_index(), gix::open::Options::isolated())?; + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 2, + "initial commit and the first crate" + ); + assert!(!repo.is_shallow()); + + Package::new("bar", "1.1.0").publish(); + p.cargo("update") + .arg("-Zgitoxide=fetch,shallow-index") + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + let shallow_repo = gix::open_opts( + find_remote_index(RepoMode::Shallow), + gix::open::Options::isolated(), + )?; + assert_eq!( + shallow_repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "the follow up clones an entirely new index which is now shallow and which is in its own location" + ); + assert!(shallow_repo.is_shallow()); + + Package::new("bar", "1.2.0").publish(); + Package::new("bar", "1.3.0").publish(); + p.cargo("update") + .arg("-Zgitoxide=fetch,shallow-index") + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + assert_eq!( + shallow_repo + .rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "subsequent shallow fetches wont' fetch what's inbetween, only the single commit that we need while leveraging existing commits" + ); + assert!(shallow_repo.is_shallow()); + + p.cargo("update") + .arg("-Zgitoxide=fetch") + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 5, + "we can separately fetch the non-shallow index as well and it sees all commits" + ); + + Ok(()) +} + +#[cargo_test] +fn gitoxide_git_dependencies_switch_from_branch_to_rev() -> anyhow::Result<()> { + // db exists from previous build, then dependency changes to refer to revision that isn't + // available in the shallow clone. + + let (bar, bar_repo) = git::new_repo("bar", |p| { + p.file("Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("src/lib.rs", "") + }); + + // this commit would not be available in a shallow clone. + let first_commit_pre_change = bar_repo.head().unwrap().target().unwrap(); + + bar.change_file("src/lib.rs", "// change"); + git::add(&bar_repo); + git::commit(&bar_repo); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = {{ git = "{}", branch = "master" }} + "#, + bar.url(), + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .arg("-Zgitoxide=fetch,shallow-deps") + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + let db_clone = gix::open_opts( + find_bar_db(RepoMode::Shallow), + gix::open::Options::isolated(), + )?; + assert!(db_clone.is_shallow()); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = {{ git = "{}", rev = "{}" }} + "#, + bar.url(), + first_commit_pre_change + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .arg("-Zgitoxide=fetch,shallow-deps") + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + assert!( + db_clone.is_shallow(), + "we maintain shallowness and never unshallow" + ); + + Ok(()) +} + +#[cargo_test] +fn shallow_deps_work_with_revisions_and_branches_mixed_on_same_dependency() -> anyhow::Result<()> { + let (bar, bar_repo) = git::new_repo("bar", |p| { + p.file("Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("src/lib.rs", "") + }); + + // this commit would not be available in a shallow clone. + let first_commit_pre_change = bar_repo.head().unwrap().target().unwrap(); + + bar.change_file("src/lib.rs", "// change"); + git::add(&bar_repo); + git::commit(&bar_repo); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar-renamed = {{ package = "bar", git = "{}", rev = "{}" }} + bar = {{ git = "{}", branch = "master" }} + "#, + bar.url(), + first_commit_pre_change, + bar.url(), + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .arg("-Zgitoxide=fetch,shallow-deps") + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + let db_paths = glob::glob(paths::home().join(".cargo/git/db/bar-*").to_str().unwrap())? + .map(Result::unwrap) + .collect::>(); + assert_eq!( + db_paths.len(), + 1, + "only one db checkout source is used per dependency" + ); + let db_clone = gix::open_opts(&db_paths[0], gix::open::Options::isolated())?; + assert!( + db_clone.is_shallow(), + "the repo is shallow while having all data it needs" + ); + + Ok(()) +} + +#[cargo_test] +fn gitoxide_clones_registry_with_shallow_protocol_and_aborts_and_updates_again( +) -> anyhow::Result<()> { + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch") + .arg("-Zgitoxide=fetch,shallow-index") + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + let repo = gix::open_opts(find_index(), gix::open::Options::isolated())?; + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "shallow clones always start at depth of 1 to minimize download size" + ); + assert!(repo.is_shallow()); + let shallow_lock = repo.shallow_file().with_extension("lock"); + // adding a lock file and deleting the original simulates a left-over clone that was aborted, leaving a lock file + // in place without ever having moved it to the right location. + std::fs::write(&shallow_lock, &[])?; + std::fs::remove_file(repo.shallow_file())?; + + Package::new("bar", "1.1.0").publish(); + p.cargo("update") + .arg("-Zgitoxide=fetch,shallow-index") + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .run(); + + assert!(!shallow_lock.is_file(), "the repository was re-initialized"); + assert!(repo.is_shallow()); + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "it's a fresh shallow clone - otherwise it would have 2 commits if the previous shallow clone would still be present" + ); + + Ok(()) +} + +fn find_lexicographically_first_bar_checkout() -> std::path::PathBuf { + glob::glob( + paths::home() + .join(".cargo/git/checkouts/bar-*/*/.git") + .to_str() + .unwrap(), + ) + .unwrap() + .next() + .unwrap() + .unwrap() + .to_owned() +} + +fn find_remote_index(mode: RepoMode) -> std::path::PathBuf { + glob::glob( + paths::home() + .join(".cargo/registry/index/*") + .to_str() + .unwrap(), + ) + .unwrap() + .map(Result::unwrap) + .filter(|p| p.to_string_lossy().ends_with("-shallow") == matches!(mode, RepoMode::Shallow)) + .next() + .unwrap() +} + +/// Find a checkout directory for bar, `shallow` or not. +fn find_bar_db(mode: RepoMode) -> std::path::PathBuf { + glob::glob(paths::home().join(".cargo/git/db/bar-*").to_str().unwrap()) + .unwrap() + .map(Result::unwrap) + .filter(|p| p.to_string_lossy().ends_with("-shallow") == matches!(mode, RepoMode::Shallow)) + .next() + .unwrap() + .to_owned() +} diff --git a/tests/testsuite/main.rs b/tests/testsuite/main.rs index a1e293acd81..9afb3945940 100644 --- a/tests/testsuite/main.rs +++ b/tests/testsuite/main.rs @@ -59,6 +59,7 @@ mod generate_lockfile; mod git; mod git_auth; mod git_gc; +mod git_shallow; mod glob_targets; mod help; mod https; diff --git a/tests/testsuite/offline.rs b/tests/testsuite/offline.rs index fe54fc59df8..5f164dbeb2b 100644 --- a/tests/testsuite/offline.rs +++ b/tests/testsuite/offline.rs @@ -3,6 +3,7 @@ use cargo_test_support::{ basic_manifest, git, main_file, path2url, project, registry::{Package, RegistryBuilder}, + Execs, }; use std::fs; @@ -377,6 +378,15 @@ fn update_offline_not_cached_git() { #[cargo_test] fn cargo_compile_offline_with_cached_git_dep() { + compile_offline_with_cached_git_dep(false) +} + +#[cargo_test] +fn gitoxide_cargo_compile_offline_with_cached_git_dep_shallow_dep() { + compile_offline_with_cached_git_dep(true) +} + +fn compile_offline_with_cached_git_dep(shallow: bool) { let git_project = git::new("dep1", |project| { project .file("Cargo.toml", &basic_manifest("dep1", "0.5.0")) @@ -420,7 +430,17 @@ fn cargo_compile_offline_with_cached_git_dep() { ) .file("src/main.rs", "fn main(){}") .build(); - prj.cargo("build").run(); + let maybe_use_shallow = |mut cargo: Execs| -> Execs { + if shallow { + cargo + .arg("-Zgitoxide=fetch,shallow-deps") + .masquerade_as_nightly_cargo(&[ + "unstable features must be available for -Z gitoxide", + ]); + } + cargo + }; + maybe_use_shallow(prj.cargo("build")).run(); prj.change_file( "Cargo.toml", @@ -438,7 +458,7 @@ fn cargo_compile_offline_with_cached_git_dep() { rev2 ), ); - prj.cargo("build").run(); + maybe_use_shallow(prj.cargo("build")).run(); let p = project() .file( @@ -463,15 +483,15 @@ fn cargo_compile_offline_with_cached_git_dep() { let git_root = git_project.root(); - p.cargo("build --offline") - .with_stderr(format!( - "\ + let mut cargo = p.cargo("build --offline"); + cargo.with_stderr(format!( + "\ [COMPILING] dep1 v0.5.0 ({}#[..]) [COMPILING] foo v0.5.0 ([CWD]) [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]", - path2url(git_root), - )) - .run(); + path2url(git_root), + )); + maybe_use_shallow(cargo).run(); assert!(p.bin("foo").is_file()); @@ -496,7 +516,7 @@ fn cargo_compile_offline_with_cached_git_dep() { ), ); - p.cargo("build --offline").run(); + maybe_use_shallow(p.cargo("build --offline")).run(); p.process(&p.bin("foo")) .with_stdout("hello from cached git repo rev1\n") .run(); diff --git a/tests/testsuite/patch.rs b/tests/testsuite/patch.rs index 681c02416bb..f2f077d7d86 100644 --- a/tests/testsuite/patch.rs +++ b/tests/testsuite/patch.rs @@ -2466,7 +2466,11 @@ fn can_update_with_alt_reg() { } #[cargo_test] -fn old_git_patch() { +fn gitoxide_clones_shallow_old_git_patch() { + perform_old_git_patch(true) +} + +fn perform_old_git_patch(shallow: bool) { // Example where an old lockfile with an explicit branch="master" in Cargo.toml. Package::new("bar", "1.0.0").publish(); let (bar, bar_repo) = git::new_repo("bar", |p| { @@ -2524,7 +2528,13 @@ dependencies = [ git::commit(&bar_repo); // This *should* keep the old lock. - p.cargo("tree") + let mut cargo = p.cargo("tree"); + if shallow { + cargo + .arg("-Zgitoxide=fetch,shallow-deps") + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]); + } + cargo // .env("CARGO_LOG", "trace") .with_stderr( "\ @@ -2542,6 +2552,11 @@ foo v0.1.0 [..] .run(); } +#[cargo_test] +fn old_git_patch() { + perform_old_git_patch(false) +} + // From https://github.com/rust-lang/cargo/issues/7463 #[cargo_test] fn patch_eq_conflict_panic() {