Monorepo for Tangled
0

Configure Feed

Select the types of activity you want to include in your feed.

gitmirror: introduce gitmirror

gitmirror is just another name of knotmirror/v2. Current Knotmirror will
be gradually replaced by gitmirror except the knot-relay part.

Signed-off-by: Seongmin Lee <git@boltless.me>

Seongmin Lee (Jul 14, 2026, 4:05 AM +0900) d3d0be02 cc28a73a

+3890 -30
+2
.gitattributes
··· 1 1 api/tangled/** linguist-generated -diff 2 2 api/tangled/*_ext.go -linguist-generated diff 3 3 flake.lock -diff 4 + Cargo.lock -diff 5 + gitmirror/proto/gen/** linguist-generated -diff
+1449 -29
Cargo.lock
··· 149 149 ] 150 150 151 151 [[package]] 152 + name = "arrayvec" 153 + version = "0.7.7" 154 + source = "registry+https://github.com/rust-lang/crates.io-index" 155 + checksum = "f02882884d3e1bc524fb12c79f107f6ad0e1cfd498c536ffb494301740995dfe" 156 + 157 + [[package]] 152 158 name = "assert-json-diff" 153 159 version = "2.0.2" 154 160 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 311 317 312 318 [[package]] 313 319 name = "bitflags" 320 + version = "1.3.2" 321 + source = "registry+https://github.com/rust-lang/crates.io-index" 322 + checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 323 + 324 + [[package]] 325 + name = "bitflags" 314 326 version = "2.11.1" 315 327 source = "registry+https://github.com/rust-lang/crates.io-index" 316 328 checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" ··· 331 343 checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 332 344 dependencies = [ 333 345 "generic-array", 346 + ] 347 + 348 + [[package]] 349 + name = "block-buffer" 350 + version = "0.12.1" 351 + source = "registry+https://github.com/rust-lang/crates.io-index" 352 + checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" 353 + dependencies = [ 354 + "hybrid-array", 334 355 ] 335 356 336 357 [[package]] ··· 648 669 ] 649 670 650 671 [[package]] 672 + name = "bstr" 673 + version = "1.12.3" 674 + source = "registry+https://github.com/rust-lang/crates.io-index" 675 + checksum = "5cee35f73844aa3014bb606320a6c1f010249dbdf43342fe54b5a4f6a8ed4b79" 676 + dependencies = [ 677 + "memchr", 678 + "regex-automata", 679 + "serde_core", 680 + ] 681 + 682 + [[package]] 651 683 name = "bumpalo" 652 684 version = "3.20.3" 653 685 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 667 699 dependencies = [ 668 700 "serde", 669 701 ] 702 + 703 + [[package]] 704 + name = "bytesize" 705 + version = "2.4.0" 706 + source = "registry+https://github.com/rust-lang/crates.io-index" 707 + checksum = "49e78e506b9d7633710dab98996f22f95f3d0f488e8f1aa162830556ed9fc14d" 670 708 671 709 [[package]] 672 710 name = "cast" ··· 824 862 version = "1.1.0" 825 863 source = "registry+https://github.com/rust-lang/crates.io-index" 826 864 checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" 865 + 866 + [[package]] 867 + name = "clru" 868 + version = "0.6.3" 869 + source = "registry+https://github.com/rust-lang/crates.io-index" 870 + checksum = "197fd99cb113a8d5d9b6376f3aa817f32c1078f2343b714fff7d2ca44fdf67d5" 871 + dependencies = [ 872 + "hashbrown 0.16.1", 873 + ] 827 874 828 875 [[package]] 829 876 name = "cobs" ··· 938 985 ] 939 986 940 987 [[package]] 988 + name = "cpufeatures" 989 + version = "0.3.0" 990 + source = "registry+https://github.com/rust-lang/crates.io-index" 991 + checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" 992 + dependencies = [ 993 + "libc", 994 + ] 995 + 996 + [[package]] 941 997 name = "crc32fast" 942 998 version = "1.5.0" 943 999 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1048 1104 ] 1049 1105 1050 1106 [[package]] 1107 + name = "crypto-common" 1108 + version = "0.2.2" 1109 + source = "registry+https://github.com/rust-lang/crates.io-index" 1110 + checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" 1111 + dependencies = [ 1112 + "hybrid-array", 1113 + ] 1114 + 1115 + [[package]] 1051 1116 name = "darling" 1052 1117 version = "0.23.0" 1053 1118 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1146 1211 checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" 1147 1212 1148 1213 [[package]] 1214 + name = "defmt" 1215 + version = "1.1.0" 1216 + source = "registry+https://github.com/rust-lang/crates.io-index" 1217 + checksum = "a6e524506490a1953d237cb87b1cfc1e46f88c18f10a22dfe0f507dc6bfc7f7f" 1218 + dependencies = [ 1219 + "bitflags 1.3.2", 1220 + "defmt-macros", 1221 + ] 1222 + 1223 + [[package]] 1224 + name = "defmt-macros" 1225 + version = "1.1.0" 1226 + source = "registry+https://github.com/rust-lang/crates.io-index" 1227 + checksum = "f0a27770e9c8f719a79d8b638281f4d828f77d8fd61e0bd94451b9b85e576a0b" 1228 + dependencies = [ 1229 + "defmt-parser", 1230 + "proc-macro-error2", 1231 + "proc-macro2", 1232 + "quote", 1233 + "syn", 1234 + ] 1235 + 1236 + [[package]] 1237 + name = "defmt-parser" 1238 + version = "1.0.0" 1239 + source = "registry+https://github.com/rust-lang/crates.io-index" 1240 + checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" 1241 + dependencies = [ 1242 + "thiserror 2.0.18", 1243 + ] 1244 + 1245 + [[package]] 1149 1246 name = "der" 1150 1247 version = "0.7.10" 1151 1248 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1199 1296 source = "registry+https://github.com/rust-lang/crates.io-index" 1200 1297 checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 1201 1298 dependencies = [ 1202 - "block-buffer", 1299 + "block-buffer 0.10.4", 1203 1300 "const-oid", 1204 - "crypto-common", 1301 + "crypto-common 0.1.6", 1205 1302 "subtle", 1303 + ] 1304 + 1305 + [[package]] 1306 + name = "digest" 1307 + version = "0.11.3" 1308 + source = "registry+https://github.com/rust-lang/crates.io-index" 1309 + checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" 1310 + dependencies = [ 1311 + "block-buffer 0.12.1", 1312 + "crypto-common 0.2.2", 1206 1313 ] 1207 1314 1208 1315 [[package]] ··· 1223 1330 checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" 1224 1331 1225 1332 [[package]] 1333 + name = "dunce" 1334 + version = "1.0.5" 1335 + source = "registry+https://github.com/rust-lang/crates.io-index" 1336 + checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" 1337 + 1338 + [[package]] 1226 1339 name = "ecdsa" 1227 1340 version = "0.16.9" 1228 1341 source = "registry+https://github.com/rust-lang/crates.io-index" 1229 1342 checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" 1230 1343 dependencies = [ 1231 1344 "der", 1232 - "digest", 1345 + "digest 0.10.7", 1233 1346 "elliptic-curve", 1234 1347 "rfc6979", 1235 1348 "signature", ··· 1250 1363 dependencies = [ 1251 1364 "base16ct", 1252 1365 "crypto-bigint", 1253 - "digest", 1366 + "digest 0.10.7", 1254 1367 "ff", 1255 1368 "generic-array", 1256 1369 "group", ··· 1317 1430 checksum = "9afc2bd4d5a73106dd53d10d73d3401c2f32730ba2c0b93ddb888a8983680471" 1318 1431 1319 1432 [[package]] 1433 + name = "faster-hex" 1434 + version = "0.10.0" 1435 + source = "registry+https://github.com/rust-lang/crates.io-index" 1436 + checksum = "7223ae2d2f179b803433d9c830478527e92b8117eab39460edae7f1614d9fb73" 1437 + dependencies = [ 1438 + "heapless 0.8.0", 1439 + "serde", 1440 + ] 1441 + 1442 + [[package]] 1320 1443 name = "fastrand" 1321 1444 version = "2.4.1" 1322 1445 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1333 1456 ] 1334 1457 1335 1458 [[package]] 1459 + name = "filetime" 1460 + version = "0.2.29" 1461 + source = "registry+https://github.com/rust-lang/crates.io-index" 1462 + checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" 1463 + dependencies = [ 1464 + "cfg-if", 1465 + "libc", 1466 + ] 1467 + 1468 + [[package]] 1336 1469 name = "find-msvc-tools" 1337 1470 version = "0.1.9" 1338 1471 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1583 1716 ] 1584 1717 1585 1718 [[package]] 1719 + name = "gitmirror" 1720 + version = "0.1.0" 1721 + dependencies = [ 1722 + "anyhow", 1723 + "clap", 1724 + "gix", 1725 + "line-numbers", 1726 + "prost", 1727 + "prost-types", 1728 + "rustc-hash", 1729 + "tempfile", 1730 + "tokio", 1731 + "tokio-stream", 1732 + "tonic", 1733 + "tonic-prost", 1734 + "tonic-prost-build", 1735 + "tracing", 1736 + "tracing-subscriber", 1737 + ] 1738 + 1739 + [[package]] 1740 + name = "gix" 1741 + version = "0.84.0" 1742 + source = "registry+https://github.com/rust-lang/crates.io-index" 1743 + checksum = "ae54ae0ebd1a5a3c3f8d95dd3b5ca6e63f4fed9bfd585e13801a97d7bde8f9ce" 1744 + dependencies = [ 1745 + "gix-actor", 1746 + "gix-archive", 1747 + "gix-attributes", 1748 + "gix-blame", 1749 + "gix-command", 1750 + "gix-commitgraph", 1751 + "gix-config", 1752 + "gix-credentials", 1753 + "gix-date", 1754 + "gix-diff", 1755 + "gix-dir", 1756 + "gix-discover", 1757 + "gix-error", 1758 + "gix-features", 1759 + "gix-filter", 1760 + "gix-fs", 1761 + "gix-glob", 1762 + "gix-hash", 1763 + "gix-hashtable", 1764 + "gix-ignore", 1765 + "gix-index", 1766 + "gix-lock", 1767 + "gix-mailmap", 1768 + "gix-merge", 1769 + "gix-negotiate", 1770 + "gix-object", 1771 + "gix-odb", 1772 + "gix-pack", 1773 + "gix-path", 1774 + "gix-pathspec", 1775 + "gix-prompt", 1776 + "gix-protocol", 1777 + "gix-ref", 1778 + "gix-refspec", 1779 + "gix-revision", 1780 + "gix-revwalk", 1781 + "gix-sec", 1782 + "gix-shallow", 1783 + "gix-status", 1784 + "gix-submodule", 1785 + "gix-tempfile", 1786 + "gix-trace", 1787 + "gix-traverse", 1788 + "gix-url", 1789 + "gix-utils", 1790 + "gix-validate", 1791 + "gix-worktree", 1792 + "gix-worktree-state", 1793 + "gix-worktree-stream", 1794 + "nonempty", 1795 + "parking_lot", 1796 + "regex", 1797 + "signal-hook", 1798 + "smallvec", 1799 + "thiserror 2.0.18", 1800 + ] 1801 + 1802 + [[package]] 1803 + name = "gix-actor" 1804 + version = "0.41.1" 1805 + source = "registry+https://github.com/rust-lang/crates.io-index" 1806 + checksum = "8bc998b8f746dda8565450d08a63b792ced9165d8c27a1ed3f02799ec6a7820f" 1807 + dependencies = [ 1808 + "bstr", 1809 + "gix-date", 1810 + "gix-error", 1811 + ] 1812 + 1813 + [[package]] 1814 + name = "gix-archive" 1815 + version = "0.33.0" 1816 + source = "registry+https://github.com/rust-lang/crates.io-index" 1817 + checksum = "16909cacc78936ab96f6c3be08379d0a2e88bfa3a7527972d2ed75c7517ef31e" 1818 + dependencies = [ 1819 + "bstr", 1820 + "gix-date", 1821 + "gix-error", 1822 + "gix-object", 1823 + "gix-worktree-stream", 1824 + ] 1825 + 1826 + [[package]] 1827 + name = "gix-attributes" 1828 + version = "0.33.2" 1829 + source = "registry+https://github.com/rust-lang/crates.io-index" 1830 + checksum = "39b40888d0ed415c0744a6cdc61eebf0304c9d26ab726725b718443c322e5ba4" 1831 + dependencies = [ 1832 + "bstr", 1833 + "gix-glob", 1834 + "gix-path", 1835 + "gix-quote", 1836 + "gix-trace", 1837 + "kstring", 1838 + "smallvec", 1839 + "thiserror 2.0.18", 1840 + "unicode-bom", 1841 + ] 1842 + 1843 + [[package]] 1844 + name = "gix-bitmap" 1845 + version = "0.3.2" 1846 + source = "registry+https://github.com/rust-lang/crates.io-index" 1847 + checksum = "52ebef0c26ad305747649e727bbcd56a7b7910754eb7cea88f6dff6f93c51283" 1848 + dependencies = [ 1849 + "gix-error", 1850 + ] 1851 + 1852 + [[package]] 1853 + name = "gix-blame" 1854 + version = "0.14.0" 1855 + source = "registry+https://github.com/rust-lang/crates.io-index" 1856 + checksum = "4d39a0c14af94c2edaa5eefe06d5ef2cdea55316ae9a9321314288e3f55fa4c0" 1857 + dependencies = [ 1858 + "gix-commitgraph", 1859 + "gix-date", 1860 + "gix-diff", 1861 + "gix-error", 1862 + "gix-hash", 1863 + "gix-object", 1864 + "gix-revwalk", 1865 + "gix-trace", 1866 + "gix-traverse", 1867 + "gix-worktree", 1868 + "smallvec", 1869 + "thiserror 2.0.18", 1870 + ] 1871 + 1872 + [[package]] 1873 + name = "gix-chunk" 1874 + version = "0.7.2" 1875 + source = "registry+https://github.com/rust-lang/crates.io-index" 1876 + checksum = "9faee47943b638e58ddd5e275a4906ad3e4b6c8584f1d41bd18ab9032ec52afb" 1877 + dependencies = [ 1878 + "gix-error", 1879 + ] 1880 + 1881 + [[package]] 1882 + name = "gix-command" 1883 + version = "0.9.1" 1884 + source = "registry+https://github.com/rust-lang/crates.io-index" 1885 + checksum = "00706d4fef135ef4b01680d5218c6ee40cda8baf697b864296cbc887d19118f6" 1886 + dependencies = [ 1887 + "bstr", 1888 + "gix-path", 1889 + "gix-quote", 1890 + "gix-trace", 1891 + "shell-words", 1892 + ] 1893 + 1894 + [[package]] 1895 + name = "gix-commitgraph" 1896 + version = "0.37.1" 1897 + source = "registry+https://github.com/rust-lang/crates.io-index" 1898 + checksum = "7f675d0df484a7f6a47e64bd6f311af489d947c0323b0564f36d14f3d7762abb" 1899 + dependencies = [ 1900 + "bstr", 1901 + "gix-chunk", 1902 + "gix-error", 1903 + "gix-hash", 1904 + "memmap2", 1905 + "nonempty", 1906 + ] 1907 + 1908 + [[package]] 1909 + name = "gix-config" 1910 + version = "0.57.0" 1911 + source = "registry+https://github.com/rust-lang/crates.io-index" 1912 + checksum = "4f2372d4b49ca28431e7d150cab9d25edc1890f0184bd57eb0e917c7799e63de" 1913 + dependencies = [ 1914 + "bstr", 1915 + "gix-config-value", 1916 + "gix-features", 1917 + "gix-glob", 1918 + "gix-path", 1919 + "gix-ref", 1920 + "gix-sec", 1921 + "smallvec", 1922 + "thiserror 2.0.18", 1923 + "unicode-bom", 1924 + ] 1925 + 1926 + [[package]] 1927 + name = "gix-config-value" 1928 + version = "0.18.1" 1929 + source = "registry+https://github.com/rust-lang/crates.io-index" 1930 + checksum = "ed42168329552f6c2e5df09665c104199d45d84bedb53683738a49b57fe1baab" 1931 + dependencies = [ 1932 + "bitflags 2.11.1", 1933 + "bstr", 1934 + "gix-path", 1935 + "libc", 1936 + "thiserror 2.0.18", 1937 + ] 1938 + 1939 + [[package]] 1940 + name = "gix-credentials" 1941 + version = "0.38.1" 1942 + source = "registry+https://github.com/rust-lang/crates.io-index" 1943 + checksum = "f40cd22f0dd71988be12d6e78b1709de2370e1957c5f107ff31e56caeba3745d" 1944 + dependencies = [ 1945 + "bstr", 1946 + "gix-command", 1947 + "gix-config-value", 1948 + "gix-date", 1949 + "gix-path", 1950 + "gix-prompt", 1951 + "gix-sec", 1952 + "gix-trace", 1953 + "gix-url", 1954 + "thiserror 2.0.18", 1955 + ] 1956 + 1957 + [[package]] 1958 + name = "gix-date" 1959 + version = "0.15.5" 1960 + source = "registry+https://github.com/rust-lang/crates.io-index" 1961 + checksum = "3d63f9e28b59ddeb1a1eb9e5cf986a9222b5d484947445edbc20473939cc7fd0" 1962 + dependencies = [ 1963 + "bstr", 1964 + "gix-error", 1965 + "itoa", 1966 + "jiff", 1967 + ] 1968 + 1969 + [[package]] 1970 + name = "gix-diff" 1971 + version = "0.64.0" 1972 + source = "registry+https://github.com/rust-lang/crates.io-index" 1973 + checksum = "3b6d9528f32d94cef2edf39a1ac01fe5a0fc44ddbb18d9e44099936047c3302b" 1974 + dependencies = [ 1975 + "bstr", 1976 + "gix-attributes", 1977 + "gix-command", 1978 + "gix-filter", 1979 + "gix-fs", 1980 + "gix-hash", 1981 + "gix-imara-diff", 1982 + "gix-index", 1983 + "gix-object", 1984 + "gix-path", 1985 + "gix-pathspec", 1986 + "gix-tempfile", 1987 + "gix-trace", 1988 + "gix-traverse", 1989 + "gix-worktree", 1990 + "thiserror 2.0.18", 1991 + ] 1992 + 1993 + [[package]] 1994 + name = "gix-dir" 1995 + version = "0.26.0" 1996 + source = "registry+https://github.com/rust-lang/crates.io-index" 1997 + checksum = "21bb2a53a6fd917ec499ed0bfb5b6887de7a15bd79197dcea7c987938749a9f1" 1998 + dependencies = [ 1999 + "bstr", 2000 + "gix-discover", 2001 + "gix-fs", 2002 + "gix-ignore", 2003 + "gix-index", 2004 + "gix-object", 2005 + "gix-path", 2006 + "gix-pathspec", 2007 + "gix-trace", 2008 + "gix-utils", 2009 + "gix-worktree", 2010 + "thiserror 2.0.18", 2011 + ] 2012 + 2013 + [[package]] 2014 + name = "gix-discover" 2015 + version = "0.52.0" 2016 + source = "registry+https://github.com/rust-lang/crates.io-index" 2017 + checksum = "77bacdd12b7879d2178a80c58c2f319995e4654e1a7a23e3181e5c8a12b824f7" 2018 + dependencies = [ 2019 + "bstr", 2020 + "dunce", 2021 + "gix-fs", 2022 + "gix-path", 2023 + "gix-ref", 2024 + "gix-sec", 2025 + "thiserror 2.0.18", 2026 + ] 2027 + 2028 + [[package]] 2029 + name = "gix-error" 2030 + version = "0.2.4" 2031 + source = "registry+https://github.com/rust-lang/crates.io-index" 2032 + checksum = "e57831e199be480af90dcd7e459abed8a174c09ec9a6e2cc8f7ca6c54598b06b" 2033 + dependencies = [ 2034 + "bstr", 2035 + ] 2036 + 2037 + [[package]] 2038 + name = "gix-features" 2039 + version = "0.48.1" 2040 + source = "registry+https://github.com/rust-lang/crates.io-index" 2041 + checksum = "1849ae154d38bc403185be14fa871e38e3c93ee606875d94e207fdb9fba52dbc" 2042 + dependencies = [ 2043 + "bytes", 2044 + "bytesize", 2045 + "crc32fast", 2046 + "crossbeam-channel", 2047 + "gix-path", 2048 + "gix-trace", 2049 + "gix-utils", 2050 + "libc", 2051 + "once_cell", 2052 + "parking_lot", 2053 + "prodash", 2054 + "thiserror 2.0.18", 2055 + "walkdir", 2056 + "zlib-rs", 2057 + ] 2058 + 2059 + [[package]] 2060 + name = "gix-filter" 2061 + version = "0.31.0" 2062 + source = "registry+https://github.com/rust-lang/crates.io-index" 2063 + checksum = "ecf74b7d16f6694ce4a3049074c41be0c7987105743674f1671807bd6dce09fa" 2064 + dependencies = [ 2065 + "bstr", 2066 + "encoding_rs", 2067 + "gix-attributes", 2068 + "gix-command", 2069 + "gix-hash", 2070 + "gix-object", 2071 + "gix-packetline", 2072 + "gix-path", 2073 + "gix-quote", 2074 + "gix-trace", 2075 + "gix-utils", 2076 + "smallvec", 2077 + "thiserror 2.0.18", 2078 + ] 2079 + 2080 + [[package]] 2081 + name = "gix-fs" 2082 + version = "0.21.2" 2083 + source = "registry+https://github.com/rust-lang/crates.io-index" 2084 + checksum = "6cdff46db8798e47e2f727d84b9379aac5add3dd3d9d0b07bb4d7d5d640771fe" 2085 + dependencies = [ 2086 + "bstr", 2087 + "fastrand", 2088 + "gix-features", 2089 + "gix-path", 2090 + "gix-utils", 2091 + "thiserror 2.0.18", 2092 + ] 2093 + 2094 + [[package]] 2095 + name = "gix-glob" 2096 + version = "0.26.1" 2097 + source = "registry+https://github.com/rust-lang/crates.io-index" 2098 + checksum = "d1fcb8ef5b16bcf874abe9b68d8abb3c0493c876d367ab824151f30a0f3f3756" 2099 + dependencies = [ 2100 + "bitflags 2.11.1", 2101 + "bstr", 2102 + "gix-features", 2103 + "gix-path", 2104 + ] 2105 + 2106 + [[package]] 2107 + name = "gix-hash" 2108 + version = "0.25.1" 2109 + source = "registry+https://github.com/rust-lang/crates.io-index" 2110 + checksum = "cb0926d3819c837750b4e03c7754901e73f68b8c9b690753a6372a1bed4eedce" 2111 + dependencies = [ 2112 + "faster-hex", 2113 + "gix-features", 2114 + "sha1-checked", 2115 + "sha2 0.11.0", 2116 + "thiserror 2.0.18", 2117 + ] 2118 + 2119 + [[package]] 2120 + name = "gix-hashtable" 2121 + version = "0.15.2" 2122 + source = "registry+https://github.com/rust-lang/crates.io-index" 2123 + checksum = "7e261d54091f0d1c729bc83f54548c071bdec60a697de1e58e88bdfd7a99d24e" 2124 + dependencies = [ 2125 + "gix-hash", 2126 + "hashbrown 0.17.1", 2127 + "parking_lot", 2128 + ] 2129 + 2130 + [[package]] 2131 + name = "gix-ignore" 2132 + version = "0.21.1" 2133 + source = "registry+https://github.com/rust-lang/crates.io-index" 2134 + checksum = "d491bab9bf2c9f341dc754f425c31d5d3f63aca615312167b82e1deeaca97d8d" 2135 + dependencies = [ 2136 + "bstr", 2137 + "gix-glob", 2138 + "gix-path", 2139 + "gix-trace", 2140 + "unicode-bom", 2141 + ] 2142 + 2143 + [[package]] 2144 + name = "gix-imara-diff" 2145 + version = "0.2.3" 2146 + source = "registry+https://github.com/rust-lang/crates.io-index" 2147 + checksum = "b305d85504de270ad3525d726a6b69cc59ee7b2269b014387651107ab9f0755b" 2148 + dependencies = [ 2149 + "bstr", 2150 + "hashbrown 0.17.1", 2151 + ] 2152 + 2153 + [[package]] 2154 + name = "gix-index" 2155 + version = "0.52.0" 2156 + source = "registry+https://github.com/rust-lang/crates.io-index" 2157 + checksum = "4e6b28cc592dc753adb58302bb14a64e412ee591a3bec77aa4df87bff74fa80d" 2158 + dependencies = [ 2159 + "bitflags 2.11.1", 2160 + "bstr", 2161 + "filetime", 2162 + "fnv", 2163 + "gix-bitmap", 2164 + "gix-features", 2165 + "gix-fs", 2166 + "gix-hash", 2167 + "gix-lock", 2168 + "gix-object", 2169 + "gix-traverse", 2170 + "gix-utils", 2171 + "gix-validate", 2172 + "hashbrown 0.17.1", 2173 + "itoa", 2174 + "libc", 2175 + "memmap2", 2176 + "rustix", 2177 + "smallvec", 2178 + "thiserror 2.0.18", 2179 + ] 2180 + 2181 + [[package]] 2182 + name = "gix-lock" 2183 + version = "23.0.1" 2184 + source = "registry+https://github.com/rust-lang/crates.io-index" 2185 + checksum = "65c9dedd9e90b0d47624d2ed241d394e09294118364e87b9b7e5f1fe755f3c2c" 2186 + dependencies = [ 2187 + "gix-tempfile", 2188 + "gix-utils", 2189 + "thiserror 2.0.18", 2190 + ] 2191 + 2192 + [[package]] 2193 + name = "gix-mailmap" 2194 + version = "0.33.1" 2195 + source = "registry+https://github.com/rust-lang/crates.io-index" 2196 + checksum = "195fd20808055824531be2fd0d34136d900e5fbca3ffb0a3c07e8beeefb9c828" 2197 + dependencies = [ 2198 + "bstr", 2199 + "gix-actor", 2200 + "gix-date", 2201 + "gix-error", 2202 + ] 2203 + 2204 + [[package]] 2205 + name = "gix-merge" 2206 + version = "0.17.0" 2207 + source = "registry+https://github.com/rust-lang/crates.io-index" 2208 + checksum = "7543e1eceb25fbbd1a29459c794148d8bafc1c77555eb386617a2d99b5371971" 2209 + dependencies = [ 2210 + "bstr", 2211 + "gix-command", 2212 + "gix-diff", 2213 + "gix-filter", 2214 + "gix-fs", 2215 + "gix-hash", 2216 + "gix-imara-diff", 2217 + "gix-index", 2218 + "gix-object", 2219 + "gix-path", 2220 + "gix-quote", 2221 + "gix-revision", 2222 + "gix-revwalk", 2223 + "gix-tempfile", 2224 + "gix-trace", 2225 + "gix-worktree", 2226 + "nonempty", 2227 + "thiserror 2.0.18", 2228 + ] 2229 + 2230 + [[package]] 2231 + name = "gix-negotiate" 2232 + version = "0.32.0" 2233 + source = "registry+https://github.com/rust-lang/crates.io-index" 2234 + checksum = "890c936a215bae25818c076cb881cb2e54d2c66ba947ba58b8dd47cff921bf55" 2235 + dependencies = [ 2236 + "bitflags 2.11.1", 2237 + "gix-commitgraph", 2238 + "gix-date", 2239 + "gix-hash", 2240 + "gix-object", 2241 + "gix-revwalk", 2242 + ] 2243 + 2244 + [[package]] 2245 + name = "gix-object" 2246 + version = "0.61.0" 2247 + source = "registry+https://github.com/rust-lang/crates.io-index" 2248 + checksum = "d5cd857e29429c7213bdef3f5aef83f8cc124774fe8ae0d27b1607d218d6d525" 2249 + dependencies = [ 2250 + "bstr", 2251 + "gix-actor", 2252 + "gix-date", 2253 + "gix-features", 2254 + "gix-hash", 2255 + "gix-hashtable", 2256 + "gix-utils", 2257 + "gix-validate", 2258 + "itoa", 2259 + "smallvec", 2260 + "thiserror 2.0.18", 2261 + ] 2262 + 2263 + [[package]] 2264 + name = "gix-odb" 2265 + version = "0.81.0" 2266 + source = "registry+https://github.com/rust-lang/crates.io-index" 2267 + checksum = "7d004c32858b1556f2d7874405edb3c97dc78fc09beaa87d57bb077ee2858a7d" 2268 + dependencies = [ 2269 + "arc-swap", 2270 + "gix-features", 2271 + "gix-fs", 2272 + "gix-hash", 2273 + "gix-hashtable", 2274 + "gix-object", 2275 + "gix-pack", 2276 + "gix-path", 2277 + "gix-quote", 2278 + "memmap2", 2279 + "parking_lot", 2280 + "tempfile", 2281 + "thiserror 2.0.18", 2282 + ] 2283 + 2284 + [[package]] 2285 + name = "gix-pack" 2286 + version = "0.71.0" 2287 + source = "registry+https://github.com/rust-lang/crates.io-index" 2288 + checksum = "e43626f2a27d1033674ec1a196b845614231e6bbd949d5e21c133045ff56b174" 2289 + dependencies = [ 2290 + "clru", 2291 + "gix-chunk", 2292 + "gix-error", 2293 + "gix-features", 2294 + "gix-hash", 2295 + "gix-hashtable", 2296 + "gix-object", 2297 + "gix-path", 2298 + "memmap2", 2299 + "smallvec", 2300 + "thiserror 2.0.18", 2301 + "uluru", 2302 + ] 2303 + 2304 + [[package]] 2305 + name = "gix-packetline" 2306 + version = "0.21.5" 2307 + source = "registry+https://github.com/rust-lang/crates.io-index" 2308 + checksum = "b217dd0ee0c4021ecf169a4a519b1b4f80d15e3f3765f3dc466223dc0ac891d7" 2309 + dependencies = [ 2310 + "bstr", 2311 + "faster-hex", 2312 + "gix-trace", 2313 + "thiserror 2.0.18", 2314 + ] 2315 + 2316 + [[package]] 2317 + name = "gix-path" 2318 + version = "0.12.1" 2319 + source = "registry+https://github.com/rust-lang/crates.io-index" 2320 + checksum = "afa6ac14cd14939ea94a496ce7460daa6511c09f5b84757e9cfc6f9c8d0f93a6" 2321 + dependencies = [ 2322 + "bstr", 2323 + "gix-trace", 2324 + "gix-validate", 2325 + "thiserror 2.0.18", 2326 + ] 2327 + 2328 + [[package]] 2329 + name = "gix-pathspec" 2330 + version = "0.18.1" 2331 + source = "registry+https://github.com/rust-lang/crates.io-index" 2332 + checksum = "3050783b41ee11511e1e8fb35623df81806194f4030395f14f48ea37c2798c9f" 2333 + dependencies = [ 2334 + "bitflags 2.11.1", 2335 + "bstr", 2336 + "gix-attributes", 2337 + "gix-config-value", 2338 + "gix-glob", 2339 + "gix-path", 2340 + "thiserror 2.0.18", 2341 + ] 2342 + 2343 + [[package]] 2344 + name = "gix-prompt" 2345 + version = "0.15.1" 2346 + source = "registry+https://github.com/rust-lang/crates.io-index" 2347 + checksum = "3ee604d7746080ae7e1023bf47204bcc2c5f307bfbe2306a3c90b1bfd1a2c6d8" 2348 + dependencies = [ 2349 + "gix-command", 2350 + "gix-config-value", 2351 + "parking_lot", 2352 + "rustix", 2353 + "thiserror 2.0.18", 2354 + ] 2355 + 2356 + [[package]] 2357 + name = "gix-protocol" 2358 + version = "0.62.0" 2359 + source = "registry+https://github.com/rust-lang/crates.io-index" 2360 + checksum = "51dea3acb390707ab868f1f9584f18449eb95d869deffae96768e47d303595ee" 2361 + dependencies = [ 2362 + "bstr", 2363 + "gix-date", 2364 + "gix-features", 2365 + "gix-hash", 2366 + "gix-ref", 2367 + "gix-shallow", 2368 + "gix-transport", 2369 + "gix-utils", 2370 + "maybe-async", 2371 + "nonempty", 2372 + "thiserror 2.0.18", 2373 + ] 2374 + 2375 + [[package]] 2376 + name = "gix-quote" 2377 + version = "0.7.2" 2378 + source = "registry+https://github.com/rust-lang/crates.io-index" 2379 + checksum = "a6e541fc33cc2b783b7979040d445a0c86a2eca747c8faea4ca84230d06ae6ef" 2380 + dependencies = [ 2381 + "bstr", 2382 + "gix-error", 2383 + "gix-utils", 2384 + ] 2385 + 2386 + [[package]] 2387 + name = "gix-ref" 2388 + version = "0.64.0" 2389 + source = "registry+https://github.com/rust-lang/crates.io-index" 2390 + checksum = "4c04f64c37eb7e6feb73c7060f8dc6f381cc5de5d53249bfd450bc48a86b2e8b" 2391 + dependencies = [ 2392 + "gix-actor", 2393 + "gix-features", 2394 + "gix-fs", 2395 + "gix-hash", 2396 + "gix-lock", 2397 + "gix-object", 2398 + "gix-path", 2399 + "gix-tempfile", 2400 + "gix-utils", 2401 + "gix-validate", 2402 + "memmap2", 2403 + "thiserror 2.0.18", 2404 + ] 2405 + 2406 + [[package]] 2407 + name = "gix-refspec" 2408 + version = "0.42.0" 2409 + source = "registry+https://github.com/rust-lang/crates.io-index" 2410 + checksum = "b216ae06ec74b5f24ad0142026a997fb0a935b7410eaf9c1616fc3f0e6c5a6d3" 2411 + dependencies = [ 2412 + "bstr", 2413 + "gix-error", 2414 + "gix-glob", 2415 + "gix-hash", 2416 + "gix-revision", 2417 + "gix-validate", 2418 + "smallvec", 2419 + "thiserror 2.0.18", 2420 + ] 2421 + 2422 + [[package]] 2423 + name = "gix-revision" 2424 + version = "0.46.0" 2425 + source = "registry+https://github.com/rust-lang/crates.io-index" 2426 + checksum = "0b47c88884dd3c1a19a39da19d10211fcdea2809aadc86869b6e824a1774340f" 2427 + dependencies = [ 2428 + "bitflags 2.11.1", 2429 + "bstr", 2430 + "gix-commitgraph", 2431 + "gix-date", 2432 + "gix-error", 2433 + "gix-hash", 2434 + "gix-hashtable", 2435 + "gix-object", 2436 + "gix-revwalk", 2437 + "gix-trace", 2438 + "nonempty", 2439 + ] 2440 + 2441 + [[package]] 2442 + name = "gix-revwalk" 2443 + version = "0.32.0" 2444 + source = "registry+https://github.com/rust-lang/crates.io-index" 2445 + checksum = "85f5756abffe0917827aac683b13684ed99875bc398fa1f9b8f479b0681ef9e6" 2446 + dependencies = [ 2447 + "gix-commitgraph", 2448 + "gix-date", 2449 + "gix-error", 2450 + "gix-hash", 2451 + "gix-hashtable", 2452 + "gix-object", 2453 + "smallvec", 2454 + "thiserror 2.0.18", 2455 + ] 2456 + 2457 + [[package]] 2458 + name = "gix-sec" 2459 + version = "0.14.1" 2460 + source = "registry+https://github.com/rust-lang/crates.io-index" 2461 + checksum = "ab8519976e4c7e486270740a5400369f37940779b80bd1377d94cfa1125d01b3" 2462 + dependencies = [ 2463 + "bitflags 2.11.1", 2464 + "gix-path", 2465 + "libc", 2466 + "windows-sys 0.61.2", 2467 + ] 2468 + 2469 + [[package]] 2470 + name = "gix-shallow" 2471 + version = "0.12.1" 2472 + source = "registry+https://github.com/rust-lang/crates.io-index" 2473 + checksum = "a292fc2fe548c5dfa575479d16b445b0ddf1dd2f56f1fec6aed386f82553cd97" 2474 + dependencies = [ 2475 + "bstr", 2476 + "gix-hash", 2477 + "gix-lock", 2478 + "nonempty", 2479 + "thiserror 2.0.18", 2480 + ] 2481 + 2482 + [[package]] 2483 + name = "gix-status" 2484 + version = "0.31.0" 2485 + source = "registry+https://github.com/rust-lang/crates.io-index" 2486 + checksum = "22042e385d28a34275e029d98f4970285045be14b9073658ca897923f2ed8700" 2487 + dependencies = [ 2488 + "bstr", 2489 + "filetime", 2490 + "gix-diff", 2491 + "gix-dir", 2492 + "gix-features", 2493 + "gix-filter", 2494 + "gix-fs", 2495 + "gix-hash", 2496 + "gix-index", 2497 + "gix-object", 2498 + "gix-path", 2499 + "gix-pathspec", 2500 + "gix-worktree", 2501 + "portable-atomic", 2502 + "thiserror 2.0.18", 2503 + ] 2504 + 2505 + [[package]] 2506 + name = "gix-submodule" 2507 + version = "0.31.0" 2508 + source = "registry+https://github.com/rust-lang/crates.io-index" 2509 + checksum = "3059890ef054066c22a94bfc6a3eaba0d806aedcd630a0bc9e5783fd88884781" 2510 + dependencies = [ 2511 + "bstr", 2512 + "gix-config", 2513 + "gix-path", 2514 + "gix-pathspec", 2515 + "gix-refspec", 2516 + "gix-url", 2517 + "thiserror 2.0.18", 2518 + ] 2519 + 2520 + [[package]] 2521 + name = "gix-tempfile" 2522 + version = "23.0.2" 2523 + source = "registry+https://github.com/rust-lang/crates.io-index" 2524 + checksum = "6ef60812443484e67bf84e444cc71b4c78ae62deb822221774a4fa0c57fdb17f" 2525 + dependencies = [ 2526 + "dashmap", 2527 + "gix-fs", 2528 + "libc", 2529 + "parking_lot", 2530 + "signal-hook", 2531 + "signal-hook-registry", 2532 + "tempfile", 2533 + ] 2534 + 2535 + [[package]] 2536 + name = "gix-trace" 2537 + version = "0.1.20" 2538 + source = "registry+https://github.com/rust-lang/crates.io-index" 2539 + checksum = "44dc45eae785c0eb14173e0f152e6e224dcf4d45b6a6999a3aed22af541ad678" 2540 + 2541 + [[package]] 2542 + name = "gix-transport" 2543 + version = "0.57.2" 2544 + source = "registry+https://github.com/rust-lang/crates.io-index" 2545 + checksum = "186874f7ad1fb2f9a2f2aa9c2dabc7f9dd087bef74c1a0eee2b4a9cf0248fcb3" 2546 + dependencies = [ 2547 + "bstr", 2548 + "gix-command", 2549 + "gix-features", 2550 + "gix-packetline", 2551 + "gix-quote", 2552 + "gix-sec", 2553 + "gix-url", 2554 + "thiserror 2.0.18", 2555 + ] 2556 + 2557 + [[package]] 2558 + name = "gix-traverse" 2559 + version = "0.58.0" 2560 + source = "registry+https://github.com/rust-lang/crates.io-index" 2561 + checksum = "e8de590ecc86a3b2870665f2288324fa9f7f8672c7fc2d4e020fdd81cd1f7aed" 2562 + dependencies = [ 2563 + "bitflags 2.11.1", 2564 + "gix-commitgraph", 2565 + "gix-date", 2566 + "gix-hash", 2567 + "gix-hashtable", 2568 + "gix-object", 2569 + "gix-revwalk", 2570 + "smallvec", 2571 + "thiserror 2.0.18", 2572 + ] 2573 + 2574 + [[package]] 2575 + name = "gix-url" 2576 + version = "0.36.1" 2577 + source = "registry+https://github.com/rust-lang/crates.io-index" 2578 + checksum = "65bb01ec69d55e82ccb7a19e264501ead4e6aac38463a8cebfdd81e22bb67ab2" 2579 + dependencies = [ 2580 + "bstr", 2581 + "gix-path", 2582 + "percent-encoding", 2583 + "thiserror 2.0.18", 2584 + ] 2585 + 2586 + [[package]] 2587 + name = "gix-utils" 2588 + version = "0.3.3" 2589 + source = "registry+https://github.com/rust-lang/crates.io-index" 2590 + checksum = "66c50966184123caf580ffa64e28031a878597f1c7fceb8fe19566c38eb1b771" 2591 + dependencies = [ 2592 + "bstr", 2593 + "fastrand", 2594 + "unicode-normalization", 2595 + ] 2596 + 2597 + [[package]] 2598 + name = "gix-validate" 2599 + version = "0.11.2" 2600 + source = "registry+https://github.com/rust-lang/crates.io-index" 2601 + checksum = "7bc6fc771c4063ba7cd2f47b91fb6076251c6a823b64b7fe7b8874b0fe4afae3" 2602 + dependencies = [ 2603 + "bstr", 2604 + ] 2605 + 2606 + [[package]] 2607 + name = "gix-worktree" 2608 + version = "0.53.0" 2609 + source = "registry+https://github.com/rust-lang/crates.io-index" 2610 + checksum = "cef414ed275e8407cd5d53d301e83be19700b0dd3f859d2434417b58f454a2d1" 2611 + dependencies = [ 2612 + "bstr", 2613 + "gix-attributes", 2614 + "gix-fs", 2615 + "gix-glob", 2616 + "gix-hash", 2617 + "gix-ignore", 2618 + "gix-index", 2619 + "gix-object", 2620 + "gix-path", 2621 + "gix-validate", 2622 + ] 2623 + 2624 + [[package]] 2625 + name = "gix-worktree-state" 2626 + version = "0.31.0" 2627 + source = "registry+https://github.com/rust-lang/crates.io-index" 2628 + checksum = "4bffae8b3ca258fdd50370cd51f06deb4c76a3b43db3868bc28dde45ffa77d69" 2629 + dependencies = [ 2630 + "bstr", 2631 + "gix-features", 2632 + "gix-filter", 2633 + "gix-fs", 2634 + "gix-index", 2635 + "gix-object", 2636 + "gix-path", 2637 + "gix-worktree", 2638 + "io-close", 2639 + "thiserror 2.0.18", 2640 + ] 2641 + 2642 + [[package]] 2643 + name = "gix-worktree-stream" 2644 + version = "0.33.0" 2645 + source = "registry+https://github.com/rust-lang/crates.io-index" 2646 + checksum = "d25e9ed30100c63f7590bc581c225e53f731a53e06aa79a245739c07f7dcc557" 2647 + dependencies = [ 2648 + "gix-attributes", 2649 + "gix-error", 2650 + "gix-features", 2651 + "gix-filter", 2652 + "gix-fs", 2653 + "gix-hash", 2654 + "gix-object", 2655 + "gix-path", 2656 + "gix-traverse", 2657 + "parking_lot", 2658 + ] 2659 + 2660 + [[package]] 1586 2661 name = "group" 1587 2662 version = "0.13.0" 1588 2663 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1633 2708 ] 1634 2709 1635 2710 [[package]] 2711 + name = "hash32" 2712 + version = "0.3.1" 2713 + source = "registry+https://github.com/rust-lang/crates.io-index" 2714 + checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" 2715 + dependencies = [ 2716 + "byteorder", 2717 + ] 2718 + 2719 + [[package]] 1636 2720 name = "hashbrown" 1637 2721 version = "0.14.5" 1638 2722 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1669 2753 version = "0.17.1" 1670 2754 source = "registry+https://github.com/rust-lang/crates.io-index" 1671 2755 checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" 2756 + dependencies = [ 2757 + "allocator-api2", 2758 + "equivalent", 2759 + "foldhash 0.2.0", 2760 + ] 1672 2761 1673 2762 [[package]] 1674 2763 name = "heapless" ··· 1677 2766 checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" 1678 2767 dependencies = [ 1679 2768 "atomic-polyfill", 1680 - "hash32", 2769 + "hash32 0.2.1", 1681 2770 "rustc_version", 1682 2771 "serde", 1683 2772 "spin 0.9.8", 2773 + "stable_deref_trait", 2774 + ] 2775 + 2776 + [[package]] 2777 + name = "heapless" 2778 + version = "0.8.0" 2779 + source = "registry+https://github.com/rust-lang/crates.io-index" 2780 + checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" 2781 + dependencies = [ 2782 + "hash32 0.3.1", 1684 2783 "stable_deref_trait", 1685 2784 ] 1686 2785 ··· 1714 2813 source = "registry+https://github.com/rust-lang/crates.io-index" 1715 2814 checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 1716 2815 dependencies = [ 1717 - "digest", 2816 + "digest 0.10.7", 1718 2817 ] 1719 2818 1720 2819 [[package]] ··· 1769 2868 checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 1770 2869 1771 2870 [[package]] 2871 + name = "human_format" 2872 + version = "1.2.1" 2873 + source = "registry+https://github.com/rust-lang/crates.io-index" 2874 + checksum = "eaec953f16e5bcf6b8a3cb3aa959b17e5577dbd2693e94554c462c08be22624b" 2875 + 2876 + [[package]] 2877 + name = "hybrid-array" 2878 + version = "0.4.12" 2879 + source = "registry+https://github.com/rust-lang/crates.io-index" 2880 + checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" 2881 + dependencies = [ 2882 + "typenum", 2883 + ] 2884 + 2885 + [[package]] 1772 2886 name = "hyper" 1773 2887 version = "1.10.0" 1774 2888 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1807 2921 ] 1808 2922 1809 2923 [[package]] 2924 + name = "hyper-timeout" 2925 + version = "0.5.2" 2926 + source = "registry+https://github.com/rust-lang/crates.io-index" 2927 + checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" 2928 + dependencies = [ 2929 + "hyper", 2930 + "hyper-util", 2931 + "pin-project-lite", 2932 + "tokio", 2933 + "tower-service", 2934 + ] 2935 + 2936 + [[package]] 1810 2937 name = "hyper-util" 1811 2938 version = "0.1.20" 1812 2939 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1992 3119 ] 1993 3120 1994 3121 [[package]] 3122 + name = "io-close" 3123 + version = "0.3.7" 3124 + source = "registry+https://github.com/rust-lang/crates.io-index" 3125 + checksum = "9cadcf447f06744f8ce713d2d6239bb5bde2c357a452397a9ed90c625da390bc" 3126 + dependencies = [ 3127 + "libc", 3128 + "winapi", 3129 + ] 3130 + 3131 + [[package]] 1995 3132 name = "ipld-core" 1996 3133 version = "0.4.3" 1997 3134 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2126 3263 "serde_path_to_error", 2127 3264 "serde_repr", 2128 3265 "serde_with", 2129 - "sha2", 3266 + "sha2 0.10.9", 2130 3267 "syn", 2131 3268 "thiserror 2.0.18", 2132 3269 "unicode-segmentation", 2133 3270 ] 2134 3271 2135 3272 [[package]] 3273 + name = "jiff" 3274 + version = "0.2.29" 3275 + source = "registry+https://github.com/rust-lang/crates.io-index" 3276 + checksum = "34f877a98676d2fb664698d74cc6a51ce6c484ce8c770f05d0108ec9090aeb46" 3277 + dependencies = [ 3278 + "defmt", 3279 + "jiff-static", 3280 + "jiff-tzdb-platform", 3281 + "log", 3282 + "portable-atomic", 3283 + "portable-atomic-util", 3284 + "serde_core", 3285 + "windows-link", 3286 + ] 3287 + 3288 + [[package]] 3289 + name = "jiff-static" 3290 + version = "0.2.29" 3291 + source = "registry+https://github.com/rust-lang/crates.io-index" 3292 + checksum = "0666b5ab5ecaca213fc2a85b8c0083d9004e84ee2d5f9a7e0017aaf50986f25f" 3293 + dependencies = [ 3294 + "proc-macro2", 3295 + "quote", 3296 + "syn", 3297 + ] 3298 + 3299 + [[package]] 3300 + name = "jiff-tzdb" 3301 + version = "0.1.6" 3302 + source = "registry+https://github.com/rust-lang/crates.io-index" 3303 + checksum = "c900ef84826f1338a557697dc8fc601df9ca9af4ac137c7fb61d4c6f2dfd3076" 3304 + 3305 + [[package]] 3306 + name = "jiff-tzdb-platform" 3307 + version = "0.1.3" 3308 + source = "registry+https://github.com/rust-lang/crates.io-index" 3309 + checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" 3310 + dependencies = [ 3311 + "jiff-tzdb", 3312 + ] 3313 + 3314 + [[package]] 2136 3315 name = "jobserver" 2137 3316 version = "0.1.34" 2138 3317 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2163 3342 "cfg-if", 2164 3343 "ecdsa", 2165 3344 "elliptic-curve", 2166 - "sha2", 3345 + "sha2 0.10.9", 3346 + ] 3347 + 3348 + [[package]] 3349 + name = "kstring" 3350 + version = "2.0.2" 3351 + source = "registry+https://github.com/rust-lang/crates.io-index" 3352 + checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1" 3353 + dependencies = [ 3354 + "static_assertions", 2167 3355 ] 2168 3356 2169 3357 [[package]] ··· 2199 3387 version = "0.2.186" 2200 3388 source = "registry+https://github.com/rust-lang/crates.io-index" 2201 3389 checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" 3390 + 3391 + [[package]] 3392 + name = "line-numbers" 3393 + version = "0.4.0" 3394 + source = "registry+https://github.com/rust-lang/crates.io-index" 3395 + checksum = "24ab6409a2f9ffae158ae823a012a7d7d68386663a14bedc260ca66eacf65c2c" 2202 3396 2203 3397 [[package]] 2204 3398 name = "linux-raw-sys" ··· 2301 3495 checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" 2302 3496 2303 3497 [[package]] 3498 + name = "maybe-async" 3499 + version = "0.2.11" 3500 + source = "registry+https://github.com/rust-lang/crates.io-index" 3501 + checksum = "746873a384ad60adc5db74471dfaba74bd278afbdcfd81db93fafcdfc8b5ca0c" 3502 + dependencies = [ 3503 + "proc-macro2", 3504 + "quote", 3505 + "syn", 3506 + ] 3507 + 3508 + [[package]] 2304 3509 name = "measure_time" 2305 3510 version = "0.9.0" 2306 3511 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2464 3669 source = "registry+https://github.com/rust-lang/crates.io-index" 2465 3670 checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" 2466 3671 dependencies = [ 2467 - "bitflags", 3672 + "bitflags 2.11.1", 2468 3673 "cfg-if", 2469 3674 "cfg_aliases", 2470 3675 "libc", ··· 2482 3687 ] 2483 3688 2484 3689 [[package]] 3690 + name = "nonempty" 3691 + version = "0.12.0" 3692 + source = "registry+https://github.com/rust-lang/crates.io-index" 3693 + checksum = "9737e026353e5cd0736f98eddae28665118eb6f6600902a7f50db585621fecb6" 3694 + 3695 + [[package]] 2485 3696 name = "nu-ansi-term" 2486 3697 version = "0.50.3" 2487 3698 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2614 3825 "ecdsa", 2615 3826 "elliptic-curve", 2616 3827 "primeorder", 2617 - "sha2", 3828 + "sha2 0.10.9", 2618 3829 ] 2619 3830 2620 3831 [[package]] ··· 2779 3990 checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" 2780 3991 2781 3992 [[package]] 3993 + name = "portable-atomic-util" 3994 + version = "0.2.7" 3995 + source = "registry+https://github.com/rust-lang/crates.io-index" 3996 + checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" 3997 + dependencies = [ 3998 + "portable-atomic", 3999 + ] 4000 + 4001 + [[package]] 2782 4002 name = "postcard" 2783 4003 version = "1.1.3" 2784 4004 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2787 4007 "cobs", 2788 4008 "embedded-io 0.4.0", 2789 4009 "embedded-io 0.6.1", 2790 - "heapless", 4010 + "heapless 0.7.17", 2791 4011 "serde", 2792 4012 ] 2793 4013 ··· 2835 4055 ] 2836 4056 2837 4057 [[package]] 4058 + name = "proc-macro-error-attr2" 4059 + version = "2.0.0" 4060 + source = "registry+https://github.com/rust-lang/crates.io-index" 4061 + checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" 4062 + dependencies = [ 4063 + "proc-macro2", 4064 + "quote", 4065 + ] 4066 + 4067 + [[package]] 4068 + name = "proc-macro-error2" 4069 + version = "2.0.1" 4070 + source = "registry+https://github.com/rust-lang/crates.io-index" 4071 + checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" 4072 + dependencies = [ 4073 + "proc-macro-error-attr2", 4074 + "proc-macro2", 4075 + "quote", 4076 + "syn", 4077 + ] 4078 + 4079 + [[package]] 2838 4080 name = "proc-macro2" 2839 4081 version = "1.0.106" 2840 4082 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2857 4099 ] 2858 4100 2859 4101 [[package]] 4102 + name = "prodash" 4103 + version = "31.0.0" 4104 + source = "registry+https://github.com/rust-lang/crates.io-index" 4105 + checksum = "962200e2d7d551451297d9fdce85138374019ada198e30ea9ede38034e27604c" 4106 + dependencies = [ 4107 + "bytesize", 4108 + "human_format", 4109 + "parking_lot", 4110 + ] 4111 + 4112 + [[package]] 2860 4113 name = "prost" 2861 - version = "0.14.3" 4114 + version = "0.14.4" 2862 4115 source = "registry+https://github.com/rust-lang/crates.io-index" 2863 - checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" 4116 + checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1" 2864 4117 dependencies = [ 2865 4118 "bytes", 2866 4119 "prost-derive", ··· 2880 4133 "prettyplease", 2881 4134 "prost", 2882 4135 "prost-types", 4136 + "pulldown-cmark", 4137 + "pulldown-cmark-to-cmark", 2883 4138 "regex", 2884 4139 "syn", 2885 4140 "tempfile", ··· 2887 4142 2888 4143 [[package]] 2889 4144 name = "prost-derive" 2890 - version = "0.14.3" 4145 + version = "0.14.4" 2891 4146 source = "registry+https://github.com/rust-lang/crates.io-index" 2892 - checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" 4147 + checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" 2893 4148 dependencies = [ 2894 4149 "anyhow", 2895 4150 "itertools 0.14.0", ··· 2967 4222 2968 4223 [[package]] 2969 4224 name = "prost-types" 2970 - version = "0.14.3" 4225 + version = "0.14.4" 2971 4226 source = "registry+https://github.com/rust-lang/crates.io-index" 2972 - checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" 4227 + checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a" 2973 4228 dependencies = [ 2974 4229 "prost", 2975 4230 ] 2976 4231 2977 4232 [[package]] 4233 + name = "pulldown-cmark" 4234 + version = "0.13.4" 4235 + source = "registry+https://github.com/rust-lang/crates.io-index" 4236 + checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" 4237 + dependencies = [ 4238 + "bitflags 2.11.1", 4239 + "memchr", 4240 + "unicase", 4241 + ] 4242 + 4243 + [[package]] 4244 + name = "pulldown-cmark-to-cmark" 4245 + version = "22.0.0" 4246 + source = "registry+https://github.com/rust-lang/crates.io-index" 4247 + checksum = "50793def1b900256624a709439404384204a5dc3a6ec580281bfaac35e882e90" 4248 + dependencies = [ 4249 + "pulldown-cmark", 4250 + ] 4251 + 4252 + [[package]] 2978 4253 name = "quick_cache" 2979 4254 version = "0.6.22" 2980 4255 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3147 4422 source = "registry+https://github.com/rust-lang/crates.io-index" 3148 4423 checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" 3149 4424 dependencies = [ 3150 - "bitflags", 4425 + "bitflags 2.11.1", 3151 4426 ] 3152 4427 3153 4428 [[package]] ··· 3304 4579 source = "registry+https://github.com/rust-lang/crates.io-index" 3305 4580 checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" 3306 4581 dependencies = [ 3307 - "bitflags", 4582 + "bitflags 2.11.1", 3308 4583 "errno", 3309 4584 "libc", 3310 4585 "linux-raw-sys", ··· 3445 4720 source = "registry+https://github.com/rust-lang/crates.io-index" 3446 4721 checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" 3447 4722 dependencies = [ 3448 - "bitflags", 4723 + "bitflags 2.11.1", 3449 4724 "core-foundation 0.10.1", 3450 4725 "core-foundation-sys", 3451 4726 "libc", ··· 3639 4914 checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" 3640 4915 dependencies = [ 3641 4916 "cfg-if", 3642 - "cpufeatures", 3643 - "digest", 4917 + "cpufeatures 0.2.17", 4918 + "digest 0.10.7", 4919 + ] 4920 + 4921 + [[package]] 4922 + name = "sha1-checked" 4923 + version = "0.10.0" 4924 + source = "registry+https://github.com/rust-lang/crates.io-index" 4925 + checksum = "89f599ac0c323ebb1c6082821a54962b839832b03984598375bff3975b804423" 4926 + dependencies = [ 4927 + "digest 0.10.7", 4928 + "sha1", 3644 4929 ] 3645 4930 3646 4931 [[package]] ··· 3650 4935 checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" 3651 4936 dependencies = [ 3652 4937 "cfg-if", 3653 - "cpufeatures", 3654 - "digest", 4938 + "cpufeatures 0.2.17", 4939 + "digest 0.10.7", 4940 + ] 4941 + 4942 + [[package]] 4943 + name = "sha2" 4944 + version = "0.11.0" 4945 + source = "registry+https://github.com/rust-lang/crates.io-index" 4946 + checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" 4947 + dependencies = [ 4948 + "cfg-if", 4949 + "cpufeatures 0.3.0", 4950 + "digest 0.11.3", 3655 4951 ] 3656 4952 3657 4953 [[package]] ··· 3662 4958 dependencies = [ 3663 4959 "lazy_static", 3664 4960 ] 4961 + 4962 + [[package]] 4963 + name = "shell-words" 4964 + version = "1.1.1" 4965 + source = "registry+https://github.com/rust-lang/crates.io-index" 4966 + checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" 3665 4967 3666 4968 [[package]] 3667 4969 name = "shlex" ··· 3690 4992 ] 3691 4993 3692 4994 [[package]] 4995 + name = "signal-hook" 4996 + version = "0.4.4" 4997 + source = "registry+https://github.com/rust-lang/crates.io-index" 4998 + checksum = "b2a0c28ca5908dbdbcd52e6fdaa00358ab88637f8ab33e1f188dd510eb44b53d" 4999 + dependencies = [ 5000 + "libc", 5001 + "signal-hook-registry", 5002 + ] 5003 + 5004 + [[package]] 3693 5005 name = "signal-hook-registry" 3694 5006 version = "1.4.8" 3695 5007 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3705 5017 source = "registry+https://github.com/rust-lang/crates.io-index" 3706 5018 checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" 3707 5019 dependencies = [ 3708 - "digest", 5020 + "digest 0.10.7", 3709 5021 "rand_core 0.6.4", 3710 5022 ] 3711 5023 ··· 3848 5160 source = "registry+https://github.com/rust-lang/crates.io-index" 3849 5161 checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" 3850 5162 dependencies = [ 3851 - "bitflags", 5163 + "bitflags 2.11.1", 3852 5164 "core-foundation 0.9.4", 3853 5165 "system-configuration-sys", 3854 5166 ] ··· 4216 5528 "futures-core", 4217 5529 "pin-project-lite", 4218 5530 "tokio", 5531 + "tokio-util", 4219 5532 ] 4220 5533 4221 5534 [[package]] ··· 4336 5649 checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" 4337 5650 4338 5651 [[package]] 5652 + name = "tonic" 5653 + version = "0.14.6" 5654 + source = "registry+https://github.com/rust-lang/crates.io-index" 5655 + checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" 5656 + dependencies = [ 5657 + "async-trait", 5658 + "axum", 5659 + "base64", 5660 + "bytes", 5661 + "h2", 5662 + "http", 5663 + "http-body", 5664 + "http-body-util", 5665 + "hyper", 5666 + "hyper-timeout", 5667 + "hyper-util", 5668 + "percent-encoding", 5669 + "pin-project", 5670 + "socket2", 5671 + "sync_wrapper", 5672 + "tokio", 5673 + "tokio-stream", 5674 + "tower", 5675 + "tower-layer", 5676 + "tower-service", 5677 + "tracing", 5678 + ] 5679 + 5680 + [[package]] 5681 + name = "tonic-build" 5682 + version = "0.14.6" 5683 + source = "registry+https://github.com/rust-lang/crates.io-index" 5684 + checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322" 5685 + dependencies = [ 5686 + "prettyplease", 5687 + "proc-macro2", 5688 + "quote", 5689 + "syn", 5690 + ] 5691 + 5692 + [[package]] 5693 + name = "tonic-prost" 5694 + version = "0.14.6" 5695 + source = "registry+https://github.com/rust-lang/crates.io-index" 5696 + checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" 5697 + dependencies = [ 5698 + "bytes", 5699 + "prost", 5700 + "tonic", 5701 + ] 5702 + 5703 + [[package]] 5704 + name = "tonic-prost-build" 5705 + version = "0.14.6" 5706 + source = "registry+https://github.com/rust-lang/crates.io-index" 5707 + checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27" 5708 + dependencies = [ 5709 + "prettyplease", 5710 + "proc-macro2", 5711 + "prost-build", 5712 + "prost-types", 5713 + "quote", 5714 + "syn", 5715 + "tempfile", 5716 + "tonic-build", 5717 + ] 5718 + 5719 + [[package]] 4339 5720 name = "tower" 4340 5721 version = "0.5.3" 4341 5722 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4343 5724 dependencies = [ 4344 5725 "futures-core", 4345 5726 "futures-util", 5727 + "indexmap", 4346 5728 "pin-project-lite", 5729 + "slab", 4347 5730 "sync_wrapper", 4348 5731 "tokio", 5732 + "tokio-util", 4349 5733 "tower-layer", 4350 5734 "tower-service", 4351 5735 "tracing", ··· 4358 5742 checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" 4359 5743 dependencies = [ 4360 5744 "async-compression", 4361 - "bitflags", 5745 + "bitflags 2.11.1", 4362 5746 "bytes", 4363 5747 "futures-core", 4364 5748 "futures-util", ··· 4560 5944 ] 4561 5945 4562 5946 [[package]] 5947 + name = "uluru" 5948 + version = "3.1.0" 5949 + source = "registry+https://github.com/rust-lang/crates.io-index" 5950 + checksum = "7c8a2469e56e6e5095c82ccd3afb98dad95f7af7929aab6d8ba8d6e0f73657da" 5951 + dependencies = [ 5952 + "arrayvec", 5953 + ] 5954 + 5955 + [[package]] 5956 + name = "unicase" 5957 + version = "2.9.0" 5958 + source = "registry+https://github.com/rust-lang/crates.io-index" 5959 + checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" 5960 + 5961 + [[package]] 5962 + name = "unicode-bom" 5963 + version = "2.0.3" 5964 + source = "registry+https://github.com/rust-lang/crates.io-index" 5965 + checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217" 5966 + 5967 + [[package]] 4563 5968 name = "unicode-ident" 4564 5969 version = "1.0.24" 4565 5970 source = "registry+https://github.com/rust-lang/crates.io-index" 4566 5971 checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" 4567 5972 4568 5973 [[package]] 5974 + name = "unicode-normalization" 5975 + version = "0.1.25" 5976 + source = "registry+https://github.com/rust-lang/crates.io-index" 5977 + checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" 5978 + dependencies = [ 5979 + "tinyvec", 5980 + ] 5981 + 5982 + [[package]] 4569 5983 name = "unicode-segmentation" 4570 5984 version = "1.13.2" 4571 5985 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4805 6219 source = "registry+https://github.com/rust-lang/crates.io-index" 4806 6220 checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" 4807 6221 dependencies = [ 4808 - "bitflags", 6222 + "bitflags 2.11.1", 4809 6223 "hashbrown 0.15.5", 4810 6224 "indexmap", 4811 6225 "semver", ··· 5214 6628 checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" 5215 6629 dependencies = [ 5216 6630 "anyhow", 5217 - "bitflags", 6631 + "bitflags 2.11.1", 5218 6632 "indexmap", 5219 6633 "log", 5220 6634 "serde", ··· 5358 6772 "quote", 5359 6773 "syn", 5360 6774 ] 6775 + 6776 + [[package]] 6777 + name = "zlib-rs" 6778 + version = "0.6.4" 6779 + source = "registry+https://github.com/rust-lang/crates.io-index" 6780 + checksum = "977347db8caa080403f6b6b7c1cda9479a8e869316f7e13a59b19076a40f94e3" 5361 6781 5362 6782 [[package]] 5363 6783 name = "zmij"
+6 -1
Cargo.toml
··· 1 1 [workspace] 2 2 resolver = "2" 3 - members = ["bobbin/crates/*", "shuttle"] 3 + members = ["bobbin/crates/*", "shuttle", "gitmirror"] 4 4 exclude = ["sites"] 5 5 6 6 [workspace.package] ··· 84 84 85 85 tracing = "0.1" 86 86 tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt", "json"] } 87 + 88 + tonic = "0.14" 89 + tonic-prost = "0.14" 90 + tonic-prost-build = "0.14" 91 + prost = "0.14" 87 92 88 93 thiserror = "2" 89 94
+15
docker-compose.yml
··· 284 284 condition: service_started 285 285 networks: [tngl] 286 286 287 + gitmirror: 288 + build: 289 + context: . 290 + dockerfile: localinfra/gitmirror.Dockerfile 291 + restart: unless-stopped 292 + environment: 293 + RUST_LOG: gitmirror=debug 294 + GITMIRROR_ADDR: 0.0.0.0:9000 295 + GITMIRROR_REPO_BASE: /data/repos 296 + volumes: 297 + - knotmirror-data:/data 298 + - ./localinfra/certs/root.crt:/usr/local/share/ca-certificates/caddy.crt:ro 299 + networks: [tngl] 300 + 287 301 zoekt-webserver: 288 302 build: 289 303 context: https://tangled.org/boltless.me/zoekt.git#tngl ··· 392 406 - spindle.tngl.boltless.dev 393 407 - tngl.boltless.dev 394 408 - mirror.tngl.boltless.dev 409 + - gitmirror.tngl.boltless.dev 395 410 - zoekt.tngl.boltless.dev 396 411 - pdsls.tngl.boltless.dev 397 412
+3
flake.nix
··· 357 357 pkgs.protoc-gen-prost-crate 358 358 pkgs.protoc-gen-prost-serde 359 359 pkgs.protoc-gen-go 360 + pkgs.protoc-gen-go-grpc 360 361 (fenix.packages.${system}.combine [ 361 362 fenix.packages.${system}.stable.cargo 362 363 fenix.packages.${system}.stable.rustc ··· 463 464 cd "$rootDir" 464 465 echo ">>> regenerating protobuf files.." 465 466 buf generate 467 + echo ">>> regenerating gitmirror go stubs..." 468 + buf generate gitmirror --template gitmirror/buf.gen.yaml 466 469 echo ">>> generating file descriptor set for shuttle..." 467 470 buf build -o shuttle/src/gen/file_descriptor_set.bin 468 471 echo ">>> done"
+30
gitmirror/Cargo.toml
··· 1 + [package] 2 + name = "gitmirror" 3 + version = "0.1.0" 4 + edition.workspace = true 5 + license.workspace = true 6 + rust-version.workspace = true 7 + 8 + [dependencies] 9 + anyhow = { workspace = true } 10 + clap = { workspace = true } 11 + tonic = { workspace = true } 12 + tonic-prost = { workspace = true } 13 + prost = { workspace = true } 14 + tokio = { workspace = true, features = ["net", "rt-multi-thread", "sync"] } 15 + tokio-stream = { workspace = true, features = ["sync"] } 16 + tracing = "0.1" 17 + tracing-subscriber = { version = "0.3", features = ["env-filter"] } 18 + line-numbers = "0.4.0" 19 + rustc-hash = "2.1.2" 20 + gix = { version = "0.84", features = ["parallel", "blob-diff", "merge", "sha1", "sha256", "revision", "tree-editor"] } 21 + prost-types = "0.14.4" 22 + 23 + [build-dependencies] 24 + tonic-prost-build = { workspace = true } 25 + 26 + [dev-dependencies] 27 + tempfile = "3" 28 + 29 + [lints] 30 + workspace = true
+4
gitmirror/README.md
··· 1 + # Gitmirror 2 + 3 + gitmirror is alternative name of Knotmirror v2. It is designed to be run under the AppView as git syncing service. 4 + Because it's internal sync service like tap or hydrant, it uses grpc over xrpc.
+12
gitmirror/buf.gen.yaml
··· 1 + version: v2 2 + plugins: 3 + - local: protoc-gen-go 4 + out: . 5 + opt: 6 + - paths=import 7 + - module=tangled.org/core 8 + - local: protoc-gen-go-grpc 9 + out: . 10 + opt: 11 + - paths=import 12 + - module=tangled.org/core
+3
gitmirror/buf.yaml
··· 1 + version: v2 2 + modules: 3 + - path: proto
+4
gitmirror/build.rs
··· 1 + fn main() -> Result<(), Box<dyn std::error::Error>> { 2 + tonic_prost_build::compile_protos("proto/gitmirror/v1/gitmirror.proto")?; 3 + Ok(()) 4 + }
+42
gitmirror/example/client.go
··· 1 + //go:build ignore 2 + 3 + // Example: how appview will call gitmirror's GitMirrorService. 4 + // 5 + // This file is build-ignored so it never breaks `go build ./...`. It is a 6 + // copy-ready reference for wiring the client into appview once the Go stubs 7 + // are generated (see gitmirror/buf.gen.yaml). 8 + package main 9 + 10 + import ( 11 + "context" 12 + "log" 13 + "time" 14 + 15 + "google.golang.org/grpc" 16 + "google.golang.org/grpc/credentials/insecure" 17 + 18 + gitmirrorv1 "tangled.org/core/gitmirror/proto/gen" 19 + ) 20 + 21 + func main() { 22 + conn, err := grpc.NewClient("127.0.0.1:9000", 23 + grpc.WithTransportCredentials(insecure.NewCredentials())) 24 + if err != nil { 25 + log.Fatal(err) 26 + } 27 + defer conn.Close() 28 + 29 + client := gitmirrorv1.NewGitMirrorServiceClient(conn) 30 + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 31 + defer cancel() 32 + 33 + // appview converts its syntax.DID to a string via did.String(). 34 + resp, err := client.Commits(ctx, &gitmirrorv1.CommitsRequest{ 35 + Repo: "did:plc:example", 36 + Options: &gitmirrorv1.CommitsOptions{}, 37 + }) 38 + if err != nil { 39 + log.Fatal(err) 40 + } 41 + log.Println(resp.GetCommits()) 42 + }
+1119
gitmirror/proto/gen/gitmirror.pb.go
··· 1 + // Code generated by protoc-gen-go. DO NOT EDIT. 2 + // versions: 3 + // protoc-gen-go v1.36.11 4 + // protoc (unknown) 5 + // source: gitmirror/v1/gitmirror.proto 6 + 7 + package gitmirrorv1 8 + 9 + import ( 10 + protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 + protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 + timestamppb "google.golang.org/protobuf/types/known/timestamppb" 13 + reflect "reflect" 14 + sync "sync" 15 + unsafe "unsafe" 16 + ) 17 + 18 + const ( 19 + // Verify that this generated code is sufficiently up-to-date. 20 + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 21 + // Verify that runtime/protoimpl is sufficiently up-to-date. 22 + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 23 + ) 24 + 25 + type DiffRequest_ComparisonType int32 26 + 27 + const ( 28 + DiffRequest_COMPARISON_TYPE_UNSPECIFIED DiffRequest_ComparisonType = 0 29 + // Corresponds to the BASE..HEAD syntax that only returns any commits that 30 + // are in HEAD but not in BASE. 31 + DiffRequest_COMPARISON_TYPE_ONLY_IN_HEAD DiffRequest_ComparisonType = 1 32 + // Corresponds to the BASE...HEAD syntax that returns any commits that are 33 + // not in both BASE and HEAD. 34 + DiffRequest_COMPARISON_TYPE_INTERSECTION DiffRequest_ComparisonType = 2 35 + ) 36 + 37 + // Enum value maps for DiffRequest_ComparisonType. 38 + var ( 39 + DiffRequest_ComparisonType_name = map[int32]string{ 40 + 0: "COMPARISON_TYPE_UNSPECIFIED", 41 + 1: "COMPARISON_TYPE_ONLY_IN_HEAD", 42 + 2: "COMPARISON_TYPE_INTERSECTION", 43 + } 44 + DiffRequest_ComparisonType_value = map[string]int32{ 45 + "COMPARISON_TYPE_UNSPECIFIED": 0, 46 + "COMPARISON_TYPE_ONLY_IN_HEAD": 1, 47 + "COMPARISON_TYPE_INTERSECTION": 2, 48 + } 49 + ) 50 + 51 + func (x DiffRequest_ComparisonType) Enum() *DiffRequest_ComparisonType { 52 + p := new(DiffRequest_ComparisonType) 53 + *p = x 54 + return p 55 + } 56 + 57 + func (x DiffRequest_ComparisonType) String() string { 58 + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) 59 + } 60 + 61 + func (DiffRequest_ComparisonType) Descriptor() protoreflect.EnumDescriptor { 62 + return file_gitmirror_v1_gitmirror_proto_enumTypes[0].Descriptor() 63 + } 64 + 65 + func (DiffRequest_ComparisonType) Type() protoreflect.EnumType { 66 + return &file_gitmirror_v1_gitmirror_proto_enumTypes[0] 67 + } 68 + 69 + func (x DiffRequest_ComparisonType) Number() protoreflect.EnumNumber { 70 + return protoreflect.EnumNumber(x) 71 + } 72 + 73 + // Deprecated: Use DiffRequest_ComparisonType.Descriptor instead. 74 + func (DiffRequest_ComparisonType) EnumDescriptor() ([]byte, []int) { 75 + return file_gitmirror_v1_gitmirror_proto_rawDescGZIP(), []int{4, 0} 76 + } 77 + 78 + type CommitLogRequest struct { 79 + state protoimpl.MessageState `protogen:"open.v1"` 80 + // repo DID 81 + Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"` 82 + // Ranges to include in the git log (revspec, "A..B", "A...B", etc.). 83 + // At least one range, or all_refs must be specified. 84 + Ranges [][]byte `protobuf:"bytes,2,rep,name=ranges,proto3" json:"ranges,omitempty"` 85 + // If true, all refs are searched for commits. 86 + // Must not be true when ranges are given. 87 + AllRefs bool `protobuf:"varint,3,opt,name=all_refs,json=allRefs,proto3" json:"all_refs,omitempty"` 88 + // After is an optional parameter to specify the earliest commit to consider. 89 + After *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=after,proto3" json:"after,omitempty"` 90 + // Before is an optional parameter to specify the latest commit to consider. 91 + Before *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=before,proto3" json:"before,omitempty"` 92 + // MaxCommits is an optional parameter to specify the maximum number of commits 93 + // to return. If max_commits is 0, all commits that match the criteria will be 94 + // returned. 95 + MaxCommits uint32 `protobuf:"varint,6,opt,name=max_commits,json=maxCommits,proto3" json:"max_commits,omitempty"` 96 + // Skip is an optional parameter to specify the number of commits to skip. 97 + // This can be used to implement a poor mans pagination. 98 + Skip uint32 `protobuf:"varint,7,opt,name=skip,proto3" json:"skip,omitempty"` 99 + unknownFields protoimpl.UnknownFields 100 + sizeCache protoimpl.SizeCache 101 + } 102 + 103 + func (x *CommitLogRequest) Reset() { 104 + *x = CommitLogRequest{} 105 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[0] 106 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 107 + ms.StoreMessageInfo(mi) 108 + } 109 + 110 + func (x *CommitLogRequest) String() string { 111 + return protoimpl.X.MessageStringOf(x) 112 + } 113 + 114 + func (*CommitLogRequest) ProtoMessage() {} 115 + 116 + func (x *CommitLogRequest) ProtoReflect() protoreflect.Message { 117 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[0] 118 + if x != nil { 119 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 120 + if ms.LoadMessageInfo() == nil { 121 + ms.StoreMessageInfo(mi) 122 + } 123 + return ms 124 + } 125 + return mi.MessageOf(x) 126 + } 127 + 128 + // Deprecated: Use CommitLogRequest.ProtoReflect.Descriptor instead. 129 + func (*CommitLogRequest) Descriptor() ([]byte, []int) { 130 + return file_gitmirror_v1_gitmirror_proto_rawDescGZIP(), []int{0} 131 + } 132 + 133 + func (x *CommitLogRequest) GetRepo() string { 134 + if x != nil { 135 + return x.Repo 136 + } 137 + return "" 138 + } 139 + 140 + func (x *CommitLogRequest) GetRanges() [][]byte { 141 + if x != nil { 142 + return x.Ranges 143 + } 144 + return nil 145 + } 146 + 147 + func (x *CommitLogRequest) GetAllRefs() bool { 148 + if x != nil { 149 + return x.AllRefs 150 + } 151 + return false 152 + } 153 + 154 + func (x *CommitLogRequest) GetAfter() *timestamppb.Timestamp { 155 + if x != nil { 156 + return x.After 157 + } 158 + return nil 159 + } 160 + 161 + func (x *CommitLogRequest) GetBefore() *timestamppb.Timestamp { 162 + if x != nil { 163 + return x.Before 164 + } 165 + return nil 166 + } 167 + 168 + func (x *CommitLogRequest) GetMaxCommits() uint32 { 169 + if x != nil { 170 + return x.MaxCommits 171 + } 172 + return 0 173 + } 174 + 175 + func (x *CommitLogRequest) GetSkip() uint32 { 176 + if x != nil { 177 + return x.Skip 178 + } 179 + return 0 180 + } 181 + 182 + type CommitLogResponse struct { 183 + state protoimpl.MessageState `protogen:"open.v1"` 184 + Commits []*GitCommit `protobuf:"bytes,1,rep,name=commits,proto3" json:"commits,omitempty"` 185 + unknownFields protoimpl.UnknownFields 186 + sizeCache protoimpl.SizeCache 187 + } 188 + 189 + func (x *CommitLogResponse) Reset() { 190 + *x = CommitLogResponse{} 191 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[1] 192 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 193 + ms.StoreMessageInfo(mi) 194 + } 195 + 196 + func (x *CommitLogResponse) String() string { 197 + return protoimpl.X.MessageStringOf(x) 198 + } 199 + 200 + func (*CommitLogResponse) ProtoMessage() {} 201 + 202 + func (x *CommitLogResponse) ProtoReflect() protoreflect.Message { 203 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[1] 204 + if x != nil { 205 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 206 + if ms.LoadMessageInfo() == nil { 207 + ms.StoreMessageInfo(mi) 208 + } 209 + return ms 210 + } 211 + return mi.MessageOf(x) 212 + } 213 + 214 + // Deprecated: Use CommitLogResponse.ProtoReflect.Descriptor instead. 215 + func (*CommitLogResponse) Descriptor() ([]byte, []int) { 216 + return file_gitmirror_v1_gitmirror_proto_rawDescGZIP(), []int{1} 217 + } 218 + 219 + func (x *CommitLogResponse) GetCommits() []*GitCommit { 220 + if x != nil { 221 + return x.Commits 222 + } 223 + return nil 224 + } 225 + 226 + type GetBlobRequest struct { 227 + state protoimpl.MessageState `protogen:"open.v1"` 228 + // repo carries the DID as a string. 229 + Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"` 230 + // oid is the blob object id (hex). 231 + Oid string `protobuf:"bytes,2,opt,name=oid,proto3" json:"oid,omitempty"` 232 + unknownFields protoimpl.UnknownFields 233 + sizeCache protoimpl.SizeCache 234 + } 235 + 236 + func (x *GetBlobRequest) Reset() { 237 + *x = GetBlobRequest{} 238 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[2] 239 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 240 + ms.StoreMessageInfo(mi) 241 + } 242 + 243 + func (x *GetBlobRequest) String() string { 244 + return protoimpl.X.MessageStringOf(x) 245 + } 246 + 247 + func (*GetBlobRequest) ProtoMessage() {} 248 + 249 + func (x *GetBlobRequest) ProtoReflect() protoreflect.Message { 250 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[2] 251 + if x != nil { 252 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 253 + if ms.LoadMessageInfo() == nil { 254 + ms.StoreMessageInfo(mi) 255 + } 256 + return ms 257 + } 258 + return mi.MessageOf(x) 259 + } 260 + 261 + // Deprecated: Use GetBlobRequest.ProtoReflect.Descriptor instead. 262 + func (*GetBlobRequest) Descriptor() ([]byte, []int) { 263 + return file_gitmirror_v1_gitmirror_proto_rawDescGZIP(), []int{2} 264 + } 265 + 266 + func (x *GetBlobRequest) GetRepo() string { 267 + if x != nil { 268 + return x.Repo 269 + } 270 + return "" 271 + } 272 + 273 + func (x *GetBlobRequest) GetOid() string { 274 + if x != nil { 275 + return x.Oid 276 + } 277 + return "" 278 + } 279 + 280 + type BlobChunk struct { 281 + state protoimpl.MessageState `protogen:"open.v1"` 282 + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` 283 + unknownFields protoimpl.UnknownFields 284 + sizeCache protoimpl.SizeCache 285 + } 286 + 287 + func (x *BlobChunk) Reset() { 288 + *x = BlobChunk{} 289 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[3] 290 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 291 + ms.StoreMessageInfo(mi) 292 + } 293 + 294 + func (x *BlobChunk) String() string { 295 + return protoimpl.X.MessageStringOf(x) 296 + } 297 + 298 + func (*BlobChunk) ProtoMessage() {} 299 + 300 + func (x *BlobChunk) ProtoReflect() protoreflect.Message { 301 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[3] 302 + if x != nil { 303 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 304 + if ms.LoadMessageInfo() == nil { 305 + ms.StoreMessageInfo(mi) 306 + } 307 + return ms 308 + } 309 + return mi.MessageOf(x) 310 + } 311 + 312 + // Deprecated: Use BlobChunk.ProtoReflect.Descriptor instead. 313 + func (*BlobChunk) Descriptor() ([]byte, []int) { 314 + return file_gitmirror_v1_gitmirror_proto_rawDescGZIP(), []int{3} 315 + } 316 + 317 + func (x *BlobChunk) GetData() []byte { 318 + if x != nil { 319 + return x.Data 320 + } 321 + return nil 322 + } 323 + 324 + type DiffRequest struct { 325 + state protoimpl.MessageState `protogen:"open.v1"` 326 + // repo carries the DID as a string; parsing/validation is an impl detail. 327 + Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"` 328 + // base_rev_spec/head_rev_spec are commit-ish ref strings. 329 + // base_rev_spec is optional; when unset, diff head against head's first parent. 330 + BaseRevSpec []byte `protobuf:"bytes,2,opt,name=base_rev_spec,json=baseRevSpec,proto3,oneof" json:"base_rev_spec,omitempty"` 331 + HeadRevSpec []byte `protobuf:"bytes,3,opt,name=head_rev_spec,json=headRevSpec,proto3" json:"head_rev_spec,omitempty"` 332 + ComparisonType DiffRequest_ComparisonType `protobuf:"varint,4,opt,name=comparison_type,json=comparisonType,proto3,enum=gitmirror.v1.DiffRequest_ComparisonType" json:"comparison_type,omitempty"` 333 + unknownFields protoimpl.UnknownFields 334 + sizeCache protoimpl.SizeCache 335 + } 336 + 337 + func (x *DiffRequest) Reset() { 338 + *x = DiffRequest{} 339 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[4] 340 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 341 + ms.StoreMessageInfo(mi) 342 + } 343 + 344 + func (x *DiffRequest) String() string { 345 + return protoimpl.X.MessageStringOf(x) 346 + } 347 + 348 + func (*DiffRequest) ProtoMessage() {} 349 + 350 + func (x *DiffRequest) ProtoReflect() protoreflect.Message { 351 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[4] 352 + if x != nil { 353 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 354 + if ms.LoadMessageInfo() == nil { 355 + ms.StoreMessageInfo(mi) 356 + } 357 + return ms 358 + } 359 + return mi.MessageOf(x) 360 + } 361 + 362 + // Deprecated: Use DiffRequest.ProtoReflect.Descriptor instead. 363 + func (*DiffRequest) Descriptor() ([]byte, []int) { 364 + return file_gitmirror_v1_gitmirror_proto_rawDescGZIP(), []int{4} 365 + } 366 + 367 + func (x *DiffRequest) GetRepo() string { 368 + if x != nil { 369 + return x.Repo 370 + } 371 + return "" 372 + } 373 + 374 + func (x *DiffRequest) GetBaseRevSpec() []byte { 375 + if x != nil { 376 + return x.BaseRevSpec 377 + } 378 + return nil 379 + } 380 + 381 + func (x *DiffRequest) GetHeadRevSpec() []byte { 382 + if x != nil { 383 + return x.HeadRevSpec 384 + } 385 + return nil 386 + } 387 + 388 + func (x *DiffRequest) GetComparisonType() DiffRequest_ComparisonType { 389 + if x != nil { 390 + return x.ComparisonType 391 + } 392 + return DiffRequest_COMPARISON_TYPE_UNSPECIFIED 393 + } 394 + 395 + type InterdiffRequest struct { 396 + state protoimpl.MessageState `protogen:"open.v1"` 397 + // repo carries the DID as a string. 398 + Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"` 399 + // Old patch range (from_base..from_head) and new patch range (to_base..to_head). 400 + FromBase []byte `protobuf:"bytes,2,opt,name=from_base,json=fromBase,proto3" json:"from_base,omitempty"` 401 + FromHead []byte `protobuf:"bytes,3,opt,name=from_head,json=fromHead,proto3" json:"from_head,omitempty"` 402 + ToBase []byte `protobuf:"bytes,4,opt,name=to_base,json=toBase,proto3" json:"to_base,omitempty"` 403 + ToHead []byte `protobuf:"bytes,5,opt,name=to_head,json=toHead,proto3" json:"to_head,omitempty"` 404 + unknownFields protoimpl.UnknownFields 405 + sizeCache protoimpl.SizeCache 406 + } 407 + 408 + func (x *InterdiffRequest) Reset() { 409 + *x = InterdiffRequest{} 410 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[5] 411 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 412 + ms.StoreMessageInfo(mi) 413 + } 414 + 415 + func (x *InterdiffRequest) String() string { 416 + return protoimpl.X.MessageStringOf(x) 417 + } 418 + 419 + func (*InterdiffRequest) ProtoMessage() {} 420 + 421 + func (x *InterdiffRequest) ProtoReflect() protoreflect.Message { 422 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[5] 423 + if x != nil { 424 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 425 + if ms.LoadMessageInfo() == nil { 426 + ms.StoreMessageInfo(mi) 427 + } 428 + return ms 429 + } 430 + return mi.MessageOf(x) 431 + } 432 + 433 + // Deprecated: Use InterdiffRequest.ProtoReflect.Descriptor instead. 434 + func (*InterdiffRequest) Descriptor() ([]byte, []int) { 435 + return file_gitmirror_v1_gitmirror_proto_rawDescGZIP(), []int{5} 436 + } 437 + 438 + func (x *InterdiffRequest) GetRepo() string { 439 + if x != nil { 440 + return x.Repo 441 + } 442 + return "" 443 + } 444 + 445 + func (x *InterdiffRequest) GetFromBase() []byte { 446 + if x != nil { 447 + return x.FromBase 448 + } 449 + return nil 450 + } 451 + 452 + func (x *InterdiffRequest) GetFromHead() []byte { 453 + if x != nil { 454 + return x.FromHead 455 + } 456 + return nil 457 + } 458 + 459 + func (x *InterdiffRequest) GetToBase() []byte { 460 + if x != nil { 461 + return x.ToBase 462 + } 463 + return nil 464 + } 465 + 466 + func (x *InterdiffRequest) GetToHead() []byte { 467 + if x != nil { 468 + return x.ToHead 469 + } 470 + return nil 471 + } 472 + 473 + type FileContent struct { 474 + state protoimpl.MessageState `protogen:"open.v1"` 475 + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` 476 + Oid string `protobuf:"bytes,2,opt,name=oid,proto3" json:"oid,omitempty"` 477 + Size uint64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"` 478 + IsBinary bool `protobuf:"varint,4,opt,name=is_binary,json=isBinary,proto3" json:"is_binary,omitempty"` 479 + IsSubmodule bool `protobuf:"varint,5,opt,name=is_submodule,json=isSubmodule,proto3" json:"is_submodule,omitempty"` 480 + // Raw file bytes, inlined when the oid is not fetchable by the client 481 + // (e.g. interdiff) 482 + Content []byte `protobuf:"bytes,6,opt,name=content,proto3,oneof" json:"content,omitempty"` 483 + unknownFields protoimpl.UnknownFields 484 + sizeCache protoimpl.SizeCache 485 + } 486 + 487 + func (x *FileContent) Reset() { 488 + *x = FileContent{} 489 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[6] 490 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 491 + ms.StoreMessageInfo(mi) 492 + } 493 + 494 + func (x *FileContent) String() string { 495 + return protoimpl.X.MessageStringOf(x) 496 + } 497 + 498 + func (*FileContent) ProtoMessage() {} 499 + 500 + func (x *FileContent) ProtoReflect() protoreflect.Message { 501 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[6] 502 + if x != nil { 503 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 504 + if ms.LoadMessageInfo() == nil { 505 + ms.StoreMessageInfo(mi) 506 + } 507 + return ms 508 + } 509 + return mi.MessageOf(x) 510 + } 511 + 512 + // Deprecated: Use FileContent.ProtoReflect.Descriptor instead. 513 + func (*FileContent) Descriptor() ([]byte, []int) { 514 + return file_gitmirror_v1_gitmirror_proto_rawDescGZIP(), []int{6} 515 + } 516 + 517 + func (x *FileContent) GetPath() string { 518 + if x != nil { 519 + return x.Path 520 + } 521 + return "" 522 + } 523 + 524 + func (x *FileContent) GetOid() string { 525 + if x != nil { 526 + return x.Oid 527 + } 528 + return "" 529 + } 530 + 531 + func (x *FileContent) GetSize() uint64 { 532 + if x != nil { 533 + return x.Size 534 + } 535 + return 0 536 + } 537 + 538 + func (x *FileContent) GetIsBinary() bool { 539 + if x != nil { 540 + return x.IsBinary 541 + } 542 + return false 543 + } 544 + 545 + func (x *FileContent) GetIsSubmodule() bool { 546 + if x != nil { 547 + return x.IsSubmodule 548 + } 549 + return false 550 + } 551 + 552 + func (x *FileContent) GetContent() []byte { 553 + if x != nil { 554 + return x.Content 555 + } 556 + return nil 557 + } 558 + 559 + // One aligned line pair; a side is absent (None) when unset. 560 + type LinePair struct { 561 + state protoimpl.MessageState `protogen:"open.v1"` 562 + Lhs *uint32 `protobuf:"varint,1,opt,name=lhs,proto3,oneof" json:"lhs,omitempty"` 563 + Rhs *uint32 `protobuf:"varint,2,opt,name=rhs,proto3,oneof" json:"rhs,omitempty"` 564 + unknownFields protoimpl.UnknownFields 565 + sizeCache protoimpl.SizeCache 566 + } 567 + 568 + func (x *LinePair) Reset() { 569 + *x = LinePair{} 570 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[7] 571 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 572 + ms.StoreMessageInfo(mi) 573 + } 574 + 575 + func (x *LinePair) String() string { 576 + return protoimpl.X.MessageStringOf(x) 577 + } 578 + 579 + func (*LinePair) ProtoMessage() {} 580 + 581 + func (x *LinePair) ProtoReflect() protoreflect.Message { 582 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[7] 583 + if x != nil { 584 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 585 + if ms.LoadMessageInfo() == nil { 586 + ms.StoreMessageInfo(mi) 587 + } 588 + return ms 589 + } 590 + return mi.MessageOf(x) 591 + } 592 + 593 + // Deprecated: Use LinePair.ProtoReflect.Descriptor instead. 594 + func (*LinePair) Descriptor() ([]byte, []int) { 595 + return file_gitmirror_v1_gitmirror_proto_rawDescGZIP(), []int{7} 596 + } 597 + 598 + func (x *LinePair) GetLhs() uint32 { 599 + if x != nil && x.Lhs != nil { 600 + return *x.Lhs 601 + } 602 + return 0 603 + } 604 + 605 + func (x *LinePair) GetRhs() uint32 { 606 + if x != nil && x.Rhs != nil { 607 + return *x.Rhs 608 + } 609 + return 0 610 + } 611 + 612 + type Hunk struct { 613 + state protoimpl.MessageState `protogen:"open.v1"` 614 + // LineNumber (u32) sets containing novel content per side. 615 + NovelLhs []uint32 `protobuf:"varint,1,rep,packed,name=novel_lhs,json=novelLhs,proto3" json:"novel_lhs,omitempty"` 616 + NovelRhs []uint32 `protobuf:"varint,2,rep,packed,name=novel_rhs,json=novelRhs,proto3" json:"novel_rhs,omitempty"` 617 + Lines []*LinePair `protobuf:"bytes,3,rep,name=lines,proto3" json:"lines,omitempty"` 618 + unknownFields protoimpl.UnknownFields 619 + sizeCache protoimpl.SizeCache 620 + } 621 + 622 + func (x *Hunk) Reset() { 623 + *x = Hunk{} 624 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[8] 625 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 626 + ms.StoreMessageInfo(mi) 627 + } 628 + 629 + func (x *Hunk) String() string { 630 + return protoimpl.X.MessageStringOf(x) 631 + } 632 + 633 + func (*Hunk) ProtoMessage() {} 634 + 635 + func (x *Hunk) ProtoReflect() protoreflect.Message { 636 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[8] 637 + if x != nil { 638 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 639 + if ms.LoadMessageInfo() == nil { 640 + ms.StoreMessageInfo(mi) 641 + } 642 + return ms 643 + } 644 + return mi.MessageOf(x) 645 + } 646 + 647 + // Deprecated: Use Hunk.ProtoReflect.Descriptor instead. 648 + func (*Hunk) Descriptor() ([]byte, []int) { 649 + return file_gitmirror_v1_gitmirror_proto_rawDescGZIP(), []int{8} 650 + } 651 + 652 + func (x *Hunk) GetNovelLhs() []uint32 { 653 + if x != nil { 654 + return x.NovelLhs 655 + } 656 + return nil 657 + } 658 + 659 + func (x *Hunk) GetNovelRhs() []uint32 { 660 + if x != nil { 661 + return x.NovelRhs 662 + } 663 + return nil 664 + } 665 + 666 + func (x *Hunk) GetLines() []*LinePair { 667 + if x != nil { 668 + return x.Lines 669 + } 670 + return nil 671 + } 672 + 673 + // Number of bytes per side when the files differ (Rust Option<(usize, usize)>). 674 + type ByteChanges struct { 675 + state protoimpl.MessageState `protogen:"open.v1"` 676 + Lhs uint64 `protobuf:"varint,1,opt,name=lhs,proto3" json:"lhs,omitempty"` 677 + Rhs uint64 `protobuf:"varint,2,opt,name=rhs,proto3" json:"rhs,omitempty"` 678 + unknownFields protoimpl.UnknownFields 679 + sizeCache protoimpl.SizeCache 680 + } 681 + 682 + func (x *ByteChanges) Reset() { 683 + *x = ByteChanges{} 684 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[9] 685 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 686 + ms.StoreMessageInfo(mi) 687 + } 688 + 689 + func (x *ByteChanges) String() string { 690 + return protoimpl.X.MessageStringOf(x) 691 + } 692 + 693 + func (*ByteChanges) ProtoMessage() {} 694 + 695 + func (x *ByteChanges) ProtoReflect() protoreflect.Message { 696 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[9] 697 + if x != nil { 698 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 699 + if ms.LoadMessageInfo() == nil { 700 + ms.StoreMessageInfo(mi) 701 + } 702 + return ms 703 + } 704 + return mi.MessageOf(x) 705 + } 706 + 707 + // Deprecated: Use ByteChanges.ProtoReflect.Descriptor instead. 708 + func (*ByteChanges) Descriptor() ([]byte, []int) { 709 + return file_gitmirror_v1_gitmirror_proto_rawDescGZIP(), []int{9} 710 + } 711 + 712 + func (x *ByteChanges) GetLhs() uint64 { 713 + if x != nil { 714 + return x.Lhs 715 + } 716 + return 0 717 + } 718 + 719 + func (x *ByteChanges) GetRhs() uint64 { 720 + if x != nil { 721 + return x.Rhs 722 + } 723 + return 0 724 + } 725 + 726 + type FileDiff struct { 727 + state protoimpl.MessageState `protogen:"open.v1"` 728 + LhsSrc *FileContent `protobuf:"bytes,1,opt,name=lhs_src,json=lhsSrc,proto3" json:"lhs_src,omitempty"` 729 + RhsSrc *FileContent `protobuf:"bytes,2,opt,name=rhs_src,json=rhsSrc,proto3" json:"rhs_src,omitempty"` 730 + Hunks []*Hunk `protobuf:"bytes,3,rep,name=hunks,proto3" json:"hunks,omitempty"` 731 + HasByteChanges *ByteChanges `protobuf:"bytes,4,opt,name=has_byte_changes,json=hasByteChanges,proto3,oneof" json:"has_byte_changes,omitempty"` 732 + HasSyntacticChanges bool `protobuf:"varint,5,opt,name=has_syntactic_changes,json=hasSyntacticChanges,proto3" json:"has_syntactic_changes,omitempty"` // TODO: lhs_positions & rhs_positions 733 + unknownFields protoimpl.UnknownFields 734 + sizeCache protoimpl.SizeCache 735 + } 736 + 737 + func (x *FileDiff) Reset() { 738 + *x = FileDiff{} 739 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[10] 740 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 741 + ms.StoreMessageInfo(mi) 742 + } 743 + 744 + func (x *FileDiff) String() string { 745 + return protoimpl.X.MessageStringOf(x) 746 + } 747 + 748 + func (*FileDiff) ProtoMessage() {} 749 + 750 + func (x *FileDiff) ProtoReflect() protoreflect.Message { 751 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[10] 752 + if x != nil { 753 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 754 + if ms.LoadMessageInfo() == nil { 755 + ms.StoreMessageInfo(mi) 756 + } 757 + return ms 758 + } 759 + return mi.MessageOf(x) 760 + } 761 + 762 + // Deprecated: Use FileDiff.ProtoReflect.Descriptor instead. 763 + func (*FileDiff) Descriptor() ([]byte, []int) { 764 + return file_gitmirror_v1_gitmirror_proto_rawDescGZIP(), []int{10} 765 + } 766 + 767 + func (x *FileDiff) GetLhsSrc() *FileContent { 768 + if x != nil { 769 + return x.LhsSrc 770 + } 771 + return nil 772 + } 773 + 774 + func (x *FileDiff) GetRhsSrc() *FileContent { 775 + if x != nil { 776 + return x.RhsSrc 777 + } 778 + return nil 779 + } 780 + 781 + func (x *FileDiff) GetHunks() []*Hunk { 782 + if x != nil { 783 + return x.Hunks 784 + } 785 + return nil 786 + } 787 + 788 + func (x *FileDiff) GetHasByteChanges() *ByteChanges { 789 + if x != nil { 790 + return x.HasByteChanges 791 + } 792 + return nil 793 + } 794 + 795 + func (x *FileDiff) GetHasSyntacticChanges() bool { 796 + if x != nil { 797 + return x.HasSyntacticChanges 798 + } 799 + return false 800 + } 801 + 802 + type GitCommit struct { 803 + state protoimpl.MessageState `protogen:"open.v1"` 804 + Oid string `protobuf:"bytes,1,opt,name=oid,proto3" json:"oid,omitempty"` 805 + Author *GitSignature `protobuf:"bytes,2,opt,name=author,proto3" json:"author,omitempty"` 806 + Committer *GitSignature `protobuf:"bytes,3,opt,name=committer,proto3" json:"committer,omitempty"` 807 + Message []byte `protobuf:"bytes,4,opt,name=message,proto3" json:"message,omitempty"` 808 + Parents []string `protobuf:"bytes,5,rep,name=parents,proto3" json:"parents,omitempty"` 809 + ExtraHeaders map[string]string `protobuf:"bytes,6,rep,name=extra_headers,json=extraHeaders,proto3" json:"extra_headers,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` 810 + unknownFields protoimpl.UnknownFields 811 + sizeCache protoimpl.SizeCache 812 + } 813 + 814 + func (x *GitCommit) Reset() { 815 + *x = GitCommit{} 816 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[11] 817 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 818 + ms.StoreMessageInfo(mi) 819 + } 820 + 821 + func (x *GitCommit) String() string { 822 + return protoimpl.X.MessageStringOf(x) 823 + } 824 + 825 + func (*GitCommit) ProtoMessage() {} 826 + 827 + func (x *GitCommit) ProtoReflect() protoreflect.Message { 828 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[11] 829 + if x != nil { 830 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 831 + if ms.LoadMessageInfo() == nil { 832 + ms.StoreMessageInfo(mi) 833 + } 834 + return ms 835 + } 836 + return mi.MessageOf(x) 837 + } 838 + 839 + // Deprecated: Use GitCommit.ProtoReflect.Descriptor instead. 840 + func (*GitCommit) Descriptor() ([]byte, []int) { 841 + return file_gitmirror_v1_gitmirror_proto_rawDescGZIP(), []int{11} 842 + } 843 + 844 + func (x *GitCommit) GetOid() string { 845 + if x != nil { 846 + return x.Oid 847 + } 848 + return "" 849 + } 850 + 851 + func (x *GitCommit) GetAuthor() *GitSignature { 852 + if x != nil { 853 + return x.Author 854 + } 855 + return nil 856 + } 857 + 858 + func (x *GitCommit) GetCommitter() *GitSignature { 859 + if x != nil { 860 + return x.Committer 861 + } 862 + return nil 863 + } 864 + 865 + func (x *GitCommit) GetMessage() []byte { 866 + if x != nil { 867 + return x.Message 868 + } 869 + return nil 870 + } 871 + 872 + func (x *GitCommit) GetParents() []string { 873 + if x != nil { 874 + return x.Parents 875 + } 876 + return nil 877 + } 878 + 879 + func (x *GitCommit) GetExtraHeaders() map[string]string { 880 + if x != nil { 881 + return x.ExtraHeaders 882 + } 883 + return nil 884 + } 885 + 886 + type GitSignature struct { 887 + state protoimpl.MessageState `protogen:"open.v1"` 888 + Name []byte `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` 889 + Email []byte `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` 890 + Date *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=date,proto3" json:"date,omitempty"` 891 + unknownFields protoimpl.UnknownFields 892 + sizeCache protoimpl.SizeCache 893 + } 894 + 895 + func (x *GitSignature) Reset() { 896 + *x = GitSignature{} 897 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[12] 898 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 899 + ms.StoreMessageInfo(mi) 900 + } 901 + 902 + func (x *GitSignature) String() string { 903 + return protoimpl.X.MessageStringOf(x) 904 + } 905 + 906 + func (*GitSignature) ProtoMessage() {} 907 + 908 + func (x *GitSignature) ProtoReflect() protoreflect.Message { 909 + mi := &file_gitmirror_v1_gitmirror_proto_msgTypes[12] 910 + if x != nil { 911 + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 912 + if ms.LoadMessageInfo() == nil { 913 + ms.StoreMessageInfo(mi) 914 + } 915 + return ms 916 + } 917 + return mi.MessageOf(x) 918 + } 919 + 920 + // Deprecated: Use GitSignature.ProtoReflect.Descriptor instead. 921 + func (*GitSignature) Descriptor() ([]byte, []int) { 922 + return file_gitmirror_v1_gitmirror_proto_rawDescGZIP(), []int{12} 923 + } 924 + 925 + func (x *GitSignature) GetName() []byte { 926 + if x != nil { 927 + return x.Name 928 + } 929 + return nil 930 + } 931 + 932 + func (x *GitSignature) GetEmail() []byte { 933 + if x != nil { 934 + return x.Email 935 + } 936 + return nil 937 + } 938 + 939 + func (x *GitSignature) GetDate() *timestamppb.Timestamp { 940 + if x != nil { 941 + return x.Date 942 + } 943 + return nil 944 + } 945 + 946 + var File_gitmirror_v1_gitmirror_proto protoreflect.FileDescriptor 947 + 948 + const file_gitmirror_v1_gitmirror_proto_rawDesc = "" + 949 + "\n" + 950 + "\x1cgitmirror/v1/gitmirror.proto\x12\fgitmirror.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"\xf4\x01\n" + 951 + "\x10CommitLogRequest\x12\x12\n" + 952 + "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x16\n" + 953 + "\x06ranges\x18\x02 \x03(\fR\x06ranges\x12\x19\n" + 954 + "\ball_refs\x18\x03 \x01(\bR\aallRefs\x120\n" + 955 + "\x05after\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\x05after\x122\n" + 956 + "\x06before\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\x06before\x12\x1f\n" + 957 + "\vmax_commits\x18\x06 \x01(\rR\n" + 958 + "maxCommits\x12\x12\n" + 959 + "\x04skip\x18\a \x01(\rR\x04skip\"F\n" + 960 + "\x11CommitLogResponse\x121\n" + 961 + "\acommits\x18\x01 \x03(\v2\x17.gitmirror.v1.GitCommitR\acommits\"6\n" + 962 + "\x0eGetBlobRequest\x12\x12\n" + 963 + "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x10\n" + 964 + "\x03oid\x18\x02 \x01(\tR\x03oid\"\x1f\n" + 965 + "\tBlobChunk\x12\x12\n" + 966 + "\x04data\x18\x01 \x01(\fR\x04data\"\xca\x02\n" + 967 + "\vDiffRequest\x12\x12\n" + 968 + "\x04repo\x18\x01 \x01(\tR\x04repo\x12'\n" + 969 + "\rbase_rev_spec\x18\x02 \x01(\fH\x00R\vbaseRevSpec\x88\x01\x01\x12\"\n" + 970 + "\rhead_rev_spec\x18\x03 \x01(\fR\vheadRevSpec\x12Q\n" + 971 + "\x0fcomparison_type\x18\x04 \x01(\x0e2(.gitmirror.v1.DiffRequest.ComparisonTypeR\x0ecomparisonType\"u\n" + 972 + "\x0eComparisonType\x12\x1f\n" + 973 + "\x1bCOMPARISON_TYPE_UNSPECIFIED\x10\x00\x12 \n" + 974 + "\x1cCOMPARISON_TYPE_ONLY_IN_HEAD\x10\x01\x12 \n" + 975 + "\x1cCOMPARISON_TYPE_INTERSECTION\x10\x02B\x10\n" + 976 + "\x0e_base_rev_spec\"\x92\x01\n" + 977 + "\x10InterdiffRequest\x12\x12\n" + 978 + "\x04repo\x18\x01 \x01(\tR\x04repo\x12\x1b\n" + 979 + "\tfrom_base\x18\x02 \x01(\fR\bfromBase\x12\x1b\n" + 980 + "\tfrom_head\x18\x03 \x01(\fR\bfromHead\x12\x17\n" + 981 + "\ato_base\x18\x04 \x01(\fR\x06toBase\x12\x17\n" + 982 + "\ato_head\x18\x05 \x01(\fR\x06toHead\"\xb2\x01\n" + 983 + "\vFileContent\x12\x12\n" + 984 + "\x04path\x18\x01 \x01(\tR\x04path\x12\x10\n" + 985 + "\x03oid\x18\x02 \x01(\tR\x03oid\x12\x12\n" + 986 + "\x04size\x18\x03 \x01(\x04R\x04size\x12\x1b\n" + 987 + "\tis_binary\x18\x04 \x01(\bR\bisBinary\x12!\n" + 988 + "\fis_submodule\x18\x05 \x01(\bR\visSubmodule\x12\x1d\n" + 989 + "\acontent\x18\x06 \x01(\fH\x00R\acontent\x88\x01\x01B\n" + 990 + "\n" + 991 + "\b_content\"H\n" + 992 + "\bLinePair\x12\x15\n" + 993 + "\x03lhs\x18\x01 \x01(\rH\x00R\x03lhs\x88\x01\x01\x12\x15\n" + 994 + "\x03rhs\x18\x02 \x01(\rH\x01R\x03rhs\x88\x01\x01B\x06\n" + 995 + "\x04_lhsB\x06\n" + 996 + "\x04_rhs\"n\n" + 997 + "\x04Hunk\x12\x1b\n" + 998 + "\tnovel_lhs\x18\x01 \x03(\rR\bnovelLhs\x12\x1b\n" + 999 + "\tnovel_rhs\x18\x02 \x03(\rR\bnovelRhs\x12,\n" + 1000 + "\x05lines\x18\x03 \x03(\v2\x16.gitmirror.v1.LinePairR\x05lines\"1\n" + 1001 + "\vByteChanges\x12\x10\n" + 1002 + "\x03lhs\x18\x01 \x01(\x04R\x03lhs\x12\x10\n" + 1003 + "\x03rhs\x18\x02 \x01(\x04R\x03rhs\"\xaf\x02\n" + 1004 + "\bFileDiff\x122\n" + 1005 + "\alhs_src\x18\x01 \x01(\v2\x19.gitmirror.v1.FileContentR\x06lhsSrc\x122\n" + 1006 + "\arhs_src\x18\x02 \x01(\v2\x19.gitmirror.v1.FileContentR\x06rhsSrc\x12(\n" + 1007 + "\x05hunks\x18\x03 \x03(\v2\x12.gitmirror.v1.HunkR\x05hunks\x12H\n" + 1008 + "\x10has_byte_changes\x18\x04 \x01(\v2\x19.gitmirror.v1.ByteChangesH\x00R\x0ehasByteChanges\x88\x01\x01\x122\n" + 1009 + "\x15has_syntactic_changes\x18\x05 \x01(\bR\x13hasSyntacticChangesB\x13\n" + 1010 + "\x11_has_byte_changes\"\xd0\x02\n" + 1011 + "\tGitCommit\x12\x10\n" + 1012 + "\x03oid\x18\x01 \x01(\tR\x03oid\x122\n" + 1013 + "\x06author\x18\x02 \x01(\v2\x1a.gitmirror.v1.GitSignatureR\x06author\x128\n" + 1014 + "\tcommitter\x18\x03 \x01(\v2\x1a.gitmirror.v1.GitSignatureR\tcommitter\x12\x18\n" + 1015 + "\amessage\x18\x04 \x01(\fR\amessage\x12\x18\n" + 1016 + "\aparents\x18\x05 \x03(\tR\aparents\x12N\n" + 1017 + "\rextra_headers\x18\x06 \x03(\v2).gitmirror.v1.GitCommit.ExtraHeadersEntryR\fextraHeaders\x1a?\n" + 1018 + "\x11ExtraHeadersEntry\x12\x10\n" + 1019 + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + 1020 + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"h\n" + 1021 + "\fGitSignature\x12\x12\n" + 1022 + "\x04name\x18\x01 \x01(\fR\x04name\x12\x14\n" + 1023 + "\x05email\x18\x02 \x01(\fR\x05email\x12.\n" + 1024 + "\x04date\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\x04date2\xaa\x02\n" + 1025 + "\x10GitMirrorService\x12N\n" + 1026 + "\tCommitLog\x12\x1e.gitmirror.v1.CommitLogRequest\x1a\x1f.gitmirror.v1.CommitLogResponse0\x01\x12B\n" + 1027 + "\aGetBlob\x12\x1c.gitmirror.v1.GetBlobRequest\x1a\x17.gitmirror.v1.BlobChunk0\x01\x12;\n" + 1028 + "\x04Diff\x12\x19.gitmirror.v1.DiffRequest\x1a\x16.gitmirror.v1.FileDiff0\x01\x12E\n" + 1029 + "\tInterdiff\x12\x1e.gitmirror.v1.InterdiffRequest\x1a\x16.gitmirror.v1.FileDiff0\x01B2Z0tangled.org/core/gitmirror/proto/gen;gitmirrorv1b\x06proto3" 1030 + 1031 + var ( 1032 + file_gitmirror_v1_gitmirror_proto_rawDescOnce sync.Once 1033 + file_gitmirror_v1_gitmirror_proto_rawDescData []byte 1034 + ) 1035 + 1036 + func file_gitmirror_v1_gitmirror_proto_rawDescGZIP() []byte { 1037 + file_gitmirror_v1_gitmirror_proto_rawDescOnce.Do(func() { 1038 + file_gitmirror_v1_gitmirror_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gitmirror_v1_gitmirror_proto_rawDesc), len(file_gitmirror_v1_gitmirror_proto_rawDesc))) 1039 + }) 1040 + return file_gitmirror_v1_gitmirror_proto_rawDescData 1041 + } 1042 + 1043 + var file_gitmirror_v1_gitmirror_proto_enumTypes = make([]protoimpl.EnumInfo, 1) 1044 + var file_gitmirror_v1_gitmirror_proto_msgTypes = make([]protoimpl.MessageInfo, 14) 1045 + var file_gitmirror_v1_gitmirror_proto_goTypes = []any{ 1046 + (DiffRequest_ComparisonType)(0), // 0: gitmirror.v1.DiffRequest.ComparisonType 1047 + (*CommitLogRequest)(nil), // 1: gitmirror.v1.CommitLogRequest 1048 + (*CommitLogResponse)(nil), // 2: gitmirror.v1.CommitLogResponse 1049 + (*GetBlobRequest)(nil), // 3: gitmirror.v1.GetBlobRequest 1050 + (*BlobChunk)(nil), // 4: gitmirror.v1.BlobChunk 1051 + (*DiffRequest)(nil), // 5: gitmirror.v1.DiffRequest 1052 + (*InterdiffRequest)(nil), // 6: gitmirror.v1.InterdiffRequest 1053 + (*FileContent)(nil), // 7: gitmirror.v1.FileContent 1054 + (*LinePair)(nil), // 8: gitmirror.v1.LinePair 1055 + (*Hunk)(nil), // 9: gitmirror.v1.Hunk 1056 + (*ByteChanges)(nil), // 10: gitmirror.v1.ByteChanges 1057 + (*FileDiff)(nil), // 11: gitmirror.v1.FileDiff 1058 + (*GitCommit)(nil), // 12: gitmirror.v1.GitCommit 1059 + (*GitSignature)(nil), // 13: gitmirror.v1.GitSignature 1060 + nil, // 14: gitmirror.v1.GitCommit.ExtraHeadersEntry 1061 + (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp 1062 + } 1063 + var file_gitmirror_v1_gitmirror_proto_depIdxs = []int32{ 1064 + 15, // 0: gitmirror.v1.CommitLogRequest.after:type_name -> google.protobuf.Timestamp 1065 + 15, // 1: gitmirror.v1.CommitLogRequest.before:type_name -> google.protobuf.Timestamp 1066 + 12, // 2: gitmirror.v1.CommitLogResponse.commits:type_name -> gitmirror.v1.GitCommit 1067 + 0, // 3: gitmirror.v1.DiffRequest.comparison_type:type_name -> gitmirror.v1.DiffRequest.ComparisonType 1068 + 8, // 4: gitmirror.v1.Hunk.lines:type_name -> gitmirror.v1.LinePair 1069 + 7, // 5: gitmirror.v1.FileDiff.lhs_src:type_name -> gitmirror.v1.FileContent 1070 + 7, // 6: gitmirror.v1.FileDiff.rhs_src:type_name -> gitmirror.v1.FileContent 1071 + 9, // 7: gitmirror.v1.FileDiff.hunks:type_name -> gitmirror.v1.Hunk 1072 + 10, // 8: gitmirror.v1.FileDiff.has_byte_changes:type_name -> gitmirror.v1.ByteChanges 1073 + 13, // 9: gitmirror.v1.GitCommit.author:type_name -> gitmirror.v1.GitSignature 1074 + 13, // 10: gitmirror.v1.GitCommit.committer:type_name -> gitmirror.v1.GitSignature 1075 + 14, // 11: gitmirror.v1.GitCommit.extra_headers:type_name -> gitmirror.v1.GitCommit.ExtraHeadersEntry 1076 + 15, // 12: gitmirror.v1.GitSignature.date:type_name -> google.protobuf.Timestamp 1077 + 1, // 13: gitmirror.v1.GitMirrorService.CommitLog:input_type -> gitmirror.v1.CommitLogRequest 1078 + 3, // 14: gitmirror.v1.GitMirrorService.GetBlob:input_type -> gitmirror.v1.GetBlobRequest 1079 + 5, // 15: gitmirror.v1.GitMirrorService.Diff:input_type -> gitmirror.v1.DiffRequest 1080 + 6, // 16: gitmirror.v1.GitMirrorService.Interdiff:input_type -> gitmirror.v1.InterdiffRequest 1081 + 2, // 17: gitmirror.v1.GitMirrorService.CommitLog:output_type -> gitmirror.v1.CommitLogResponse 1082 + 4, // 18: gitmirror.v1.GitMirrorService.GetBlob:output_type -> gitmirror.v1.BlobChunk 1083 + 11, // 19: gitmirror.v1.GitMirrorService.Diff:output_type -> gitmirror.v1.FileDiff 1084 + 11, // 20: gitmirror.v1.GitMirrorService.Interdiff:output_type -> gitmirror.v1.FileDiff 1085 + 17, // [17:21] is the sub-list for method output_type 1086 + 13, // [13:17] is the sub-list for method input_type 1087 + 13, // [13:13] is the sub-list for extension type_name 1088 + 13, // [13:13] is the sub-list for extension extendee 1089 + 0, // [0:13] is the sub-list for field type_name 1090 + } 1091 + 1092 + func init() { file_gitmirror_v1_gitmirror_proto_init() } 1093 + func file_gitmirror_v1_gitmirror_proto_init() { 1094 + if File_gitmirror_v1_gitmirror_proto != nil { 1095 + return 1096 + } 1097 + file_gitmirror_v1_gitmirror_proto_msgTypes[4].OneofWrappers = []any{} 1098 + file_gitmirror_v1_gitmirror_proto_msgTypes[6].OneofWrappers = []any{} 1099 + file_gitmirror_v1_gitmirror_proto_msgTypes[7].OneofWrappers = []any{} 1100 + file_gitmirror_v1_gitmirror_proto_msgTypes[10].OneofWrappers = []any{} 1101 + type x struct{} 1102 + out := protoimpl.TypeBuilder{ 1103 + File: protoimpl.DescBuilder{ 1104 + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 1105 + RawDescriptor: unsafe.Slice(unsafe.StringData(file_gitmirror_v1_gitmirror_proto_rawDesc), len(file_gitmirror_v1_gitmirror_proto_rawDesc)), 1106 + NumEnums: 1, 1107 + NumMessages: 14, 1108 + NumExtensions: 0, 1109 + NumServices: 1, 1110 + }, 1111 + GoTypes: file_gitmirror_v1_gitmirror_proto_goTypes, 1112 + DependencyIndexes: file_gitmirror_v1_gitmirror_proto_depIdxs, 1113 + EnumInfos: file_gitmirror_v1_gitmirror_proto_enumTypes, 1114 + MessageInfos: file_gitmirror_v1_gitmirror_proto_msgTypes, 1115 + }.Build() 1116 + File_gitmirror_v1_gitmirror_proto = out.File 1117 + file_gitmirror_v1_gitmirror_proto_goTypes = nil 1118 + file_gitmirror_v1_gitmirror_proto_depIdxs = nil 1119 + }
+247
gitmirror/proto/gen/gitmirror_grpc.pb.go
··· 1 + // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 + // versions: 3 + // - protoc-gen-go-grpc v1.6.2 4 + // - protoc (unknown) 5 + // source: gitmirror/v1/gitmirror.proto 6 + 7 + package gitmirrorv1 8 + 9 + import ( 10 + context "context" 11 + grpc "google.golang.org/grpc" 12 + codes "google.golang.org/grpc/codes" 13 + status "google.golang.org/grpc/status" 14 + ) 15 + 16 + // This is a compile-time assertion to ensure that this generated file 17 + // is compatible with the grpc package it is being compiled against. 18 + // Requires gRPC-Go v1.64.0 or later. 19 + const _ = grpc.SupportPackageIsVersion9 20 + 21 + const ( 22 + GitMirrorService_CommitLog_FullMethodName = "/gitmirror.v1.GitMirrorService/CommitLog" 23 + GitMirrorService_GetBlob_FullMethodName = "/gitmirror.v1.GitMirrorService/GetBlob" 24 + GitMirrorService_Diff_FullMethodName = "/gitmirror.v1.GitMirrorService/Diff" 25 + GitMirrorService_Interdiff_FullMethodName = "/gitmirror.v1.GitMirrorService/Interdiff" 26 + ) 27 + 28 + // GitMirrorServiceClient is the client API for GitMirrorService service. 29 + // 30 + // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 31 + type GitMirrorServiceClient interface { 32 + CommitLog(ctx context.Context, in *CommitLogRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[CommitLogResponse], error) 33 + GetBlob(ctx context.Context, in *GetBlobRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[BlobChunk], error) 34 + Diff(ctx context.Context, in *DiffRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[FileDiff], error) 35 + Interdiff(ctx context.Context, in *InterdiffRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[FileDiff], error) 36 + } 37 + 38 + type gitMirrorServiceClient struct { 39 + cc grpc.ClientConnInterface 40 + } 41 + 42 + func NewGitMirrorServiceClient(cc grpc.ClientConnInterface) GitMirrorServiceClient { 43 + return &gitMirrorServiceClient{cc} 44 + } 45 + 46 + func (c *gitMirrorServiceClient) CommitLog(ctx context.Context, in *CommitLogRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[CommitLogResponse], error) { 47 + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) 48 + stream, err := c.cc.NewStream(ctx, &GitMirrorService_ServiceDesc.Streams[0], GitMirrorService_CommitLog_FullMethodName, cOpts...) 49 + if err != nil { 50 + return nil, err 51 + } 52 + x := &grpc.GenericClientStream[CommitLogRequest, CommitLogResponse]{ClientStream: stream} 53 + if err := x.ClientStream.SendMsg(in); err != nil { 54 + return nil, err 55 + } 56 + if err := x.ClientStream.CloseSend(); err != nil { 57 + return nil, err 58 + } 59 + return x, nil 60 + } 61 + 62 + // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. 63 + type GitMirrorService_CommitLogClient = grpc.ServerStreamingClient[CommitLogResponse] 64 + 65 + func (c *gitMirrorServiceClient) GetBlob(ctx context.Context, in *GetBlobRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[BlobChunk], error) { 66 + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) 67 + stream, err := c.cc.NewStream(ctx, &GitMirrorService_ServiceDesc.Streams[1], GitMirrorService_GetBlob_FullMethodName, cOpts...) 68 + if err != nil { 69 + return nil, err 70 + } 71 + x := &grpc.GenericClientStream[GetBlobRequest, BlobChunk]{ClientStream: stream} 72 + if err := x.ClientStream.SendMsg(in); err != nil { 73 + return nil, err 74 + } 75 + if err := x.ClientStream.CloseSend(); err != nil { 76 + return nil, err 77 + } 78 + return x, nil 79 + } 80 + 81 + // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. 82 + type GitMirrorService_GetBlobClient = grpc.ServerStreamingClient[BlobChunk] 83 + 84 + func (c *gitMirrorServiceClient) Diff(ctx context.Context, in *DiffRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[FileDiff], error) { 85 + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) 86 + stream, err := c.cc.NewStream(ctx, &GitMirrorService_ServiceDesc.Streams[2], GitMirrorService_Diff_FullMethodName, cOpts...) 87 + if err != nil { 88 + return nil, err 89 + } 90 + x := &grpc.GenericClientStream[DiffRequest, FileDiff]{ClientStream: stream} 91 + if err := x.ClientStream.SendMsg(in); err != nil { 92 + return nil, err 93 + } 94 + if err := x.ClientStream.CloseSend(); err != nil { 95 + return nil, err 96 + } 97 + return x, nil 98 + } 99 + 100 + // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. 101 + type GitMirrorService_DiffClient = grpc.ServerStreamingClient[FileDiff] 102 + 103 + func (c *gitMirrorServiceClient) Interdiff(ctx context.Context, in *InterdiffRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[FileDiff], error) { 104 + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) 105 + stream, err := c.cc.NewStream(ctx, &GitMirrorService_ServiceDesc.Streams[3], GitMirrorService_Interdiff_FullMethodName, cOpts...) 106 + if err != nil { 107 + return nil, err 108 + } 109 + x := &grpc.GenericClientStream[InterdiffRequest, FileDiff]{ClientStream: stream} 110 + if err := x.ClientStream.SendMsg(in); err != nil { 111 + return nil, err 112 + } 113 + if err := x.ClientStream.CloseSend(); err != nil { 114 + return nil, err 115 + } 116 + return x, nil 117 + } 118 + 119 + // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. 120 + type GitMirrorService_InterdiffClient = grpc.ServerStreamingClient[FileDiff] 121 + 122 + // GitMirrorServiceServer is the server API for GitMirrorService service. 123 + // All implementations must embed UnimplementedGitMirrorServiceServer 124 + // for forward compatibility. 125 + type GitMirrorServiceServer interface { 126 + CommitLog(*CommitLogRequest, grpc.ServerStreamingServer[CommitLogResponse]) error 127 + GetBlob(*GetBlobRequest, grpc.ServerStreamingServer[BlobChunk]) error 128 + Diff(*DiffRequest, grpc.ServerStreamingServer[FileDiff]) error 129 + Interdiff(*InterdiffRequest, grpc.ServerStreamingServer[FileDiff]) error 130 + mustEmbedUnimplementedGitMirrorServiceServer() 131 + } 132 + 133 + // UnimplementedGitMirrorServiceServer must be embedded to have 134 + // forward compatible implementations. 135 + // 136 + // NOTE: this should be embedded by value instead of pointer to avoid a nil 137 + // pointer dereference when methods are called. 138 + type UnimplementedGitMirrorServiceServer struct{} 139 + 140 + func (UnimplementedGitMirrorServiceServer) CommitLog(*CommitLogRequest, grpc.ServerStreamingServer[CommitLogResponse]) error { 141 + return status.Error(codes.Unimplemented, "method CommitLog not implemented") 142 + } 143 + func (UnimplementedGitMirrorServiceServer) GetBlob(*GetBlobRequest, grpc.ServerStreamingServer[BlobChunk]) error { 144 + return status.Error(codes.Unimplemented, "method GetBlob not implemented") 145 + } 146 + func (UnimplementedGitMirrorServiceServer) Diff(*DiffRequest, grpc.ServerStreamingServer[FileDiff]) error { 147 + return status.Error(codes.Unimplemented, "method Diff not implemented") 148 + } 149 + func (UnimplementedGitMirrorServiceServer) Interdiff(*InterdiffRequest, grpc.ServerStreamingServer[FileDiff]) error { 150 + return status.Error(codes.Unimplemented, "method Interdiff not implemented") 151 + } 152 + func (UnimplementedGitMirrorServiceServer) mustEmbedUnimplementedGitMirrorServiceServer() {} 153 + func (UnimplementedGitMirrorServiceServer) testEmbeddedByValue() {} 154 + 155 + // UnsafeGitMirrorServiceServer may be embedded to opt out of forward compatibility for this service. 156 + // Use of this interface is not recommended, as added methods to GitMirrorServiceServer will 157 + // result in compilation errors. 158 + type UnsafeGitMirrorServiceServer interface { 159 + mustEmbedUnimplementedGitMirrorServiceServer() 160 + } 161 + 162 + func RegisterGitMirrorServiceServer(s grpc.ServiceRegistrar, srv GitMirrorServiceServer) { 163 + // If the following call panics, it indicates UnimplementedGitMirrorServiceServer was 164 + // embedded by pointer and is nil. This will cause panics if an 165 + // unimplemented method is ever invoked, so we test this at initialization 166 + // time to prevent it from happening at runtime later due to I/O. 167 + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { 168 + t.testEmbeddedByValue() 169 + } 170 + s.RegisterService(&GitMirrorService_ServiceDesc, srv) 171 + } 172 + 173 + func _GitMirrorService_CommitLog_Handler(srv interface{}, stream grpc.ServerStream) error { 174 + m := new(CommitLogRequest) 175 + if err := stream.RecvMsg(m); err != nil { 176 + return err 177 + } 178 + return srv.(GitMirrorServiceServer).CommitLog(m, &grpc.GenericServerStream[CommitLogRequest, CommitLogResponse]{ServerStream: stream}) 179 + } 180 + 181 + // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. 182 + type GitMirrorService_CommitLogServer = grpc.ServerStreamingServer[CommitLogResponse] 183 + 184 + func _GitMirrorService_GetBlob_Handler(srv interface{}, stream grpc.ServerStream) error { 185 + m := new(GetBlobRequest) 186 + if err := stream.RecvMsg(m); err != nil { 187 + return err 188 + } 189 + return srv.(GitMirrorServiceServer).GetBlob(m, &grpc.GenericServerStream[GetBlobRequest, BlobChunk]{ServerStream: stream}) 190 + } 191 + 192 + // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. 193 + type GitMirrorService_GetBlobServer = grpc.ServerStreamingServer[BlobChunk] 194 + 195 + func _GitMirrorService_Diff_Handler(srv interface{}, stream grpc.ServerStream) error { 196 + m := new(DiffRequest) 197 + if err := stream.RecvMsg(m); err != nil { 198 + return err 199 + } 200 + return srv.(GitMirrorServiceServer).Diff(m, &grpc.GenericServerStream[DiffRequest, FileDiff]{ServerStream: stream}) 201 + } 202 + 203 + // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. 204 + type GitMirrorService_DiffServer = grpc.ServerStreamingServer[FileDiff] 205 + 206 + func _GitMirrorService_Interdiff_Handler(srv interface{}, stream grpc.ServerStream) error { 207 + m := new(InterdiffRequest) 208 + if err := stream.RecvMsg(m); err != nil { 209 + return err 210 + } 211 + return srv.(GitMirrorServiceServer).Interdiff(m, &grpc.GenericServerStream[InterdiffRequest, FileDiff]{ServerStream: stream}) 212 + } 213 + 214 + // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. 215 + type GitMirrorService_InterdiffServer = grpc.ServerStreamingServer[FileDiff] 216 + 217 + // GitMirrorService_ServiceDesc is the grpc.ServiceDesc for GitMirrorService service. 218 + // It's only intended for direct use with grpc.RegisterService, 219 + // and not to be introspected or modified (even as a copy) 220 + var GitMirrorService_ServiceDesc = grpc.ServiceDesc{ 221 + ServiceName: "gitmirror.v1.GitMirrorService", 222 + HandlerType: (*GitMirrorServiceServer)(nil), 223 + Methods: []grpc.MethodDesc{}, 224 + Streams: []grpc.StreamDesc{ 225 + { 226 + StreamName: "CommitLog", 227 + Handler: _GitMirrorService_CommitLog_Handler, 228 + ServerStreams: true, 229 + }, 230 + { 231 + StreamName: "GetBlob", 232 + Handler: _GitMirrorService_GetBlob_Handler, 233 + ServerStreams: true, 234 + }, 235 + { 236 + StreamName: "Diff", 237 + Handler: _GitMirrorService_Diff_Handler, 238 + ServerStreams: true, 239 + }, 240 + { 241 + StreamName: "Interdiff", 242 + Handler: _GitMirrorService_Interdiff_Handler, 243 + ServerStreams: true, 244 + }, 245 + }, 246 + Metadata: "gitmirror/v1/gitmirror.proto", 247 + }
+135
gitmirror/proto/gitmirror/v1/gitmirror.proto
··· 1 + syntax = "proto3"; 2 + 3 + package gitmirror.v1; 4 + 5 + import "google/protobuf/timestamp.proto"; 6 + 7 + option go_package = "tangled.org/core/gitmirror/proto/gen;gitmirrorv1"; 8 + 9 + service GitMirrorService { 10 + rpc CommitLog(CommitLogRequest) returns (stream CommitLogResponse); 11 + rpc GetBlob(GetBlobRequest) returns (stream BlobChunk); 12 + rpc Diff(DiffRequest) returns (stream FileDiff); 13 + rpc Interdiff(InterdiffRequest) returns (stream FileDiff); 14 + } 15 + 16 + message CommitLogRequest { 17 + // repo DID 18 + string repo = 1; 19 + // Ranges to include in the git log (revspec, "A..B", "A...B", etc.). 20 + // At least one range, or all_refs must be specified. 21 + repeated bytes ranges = 2; 22 + // If true, all refs are searched for commits. 23 + // Must not be true when ranges are given. 24 + bool all_refs = 3; 25 + // After is an optional parameter to specify the earliest commit to consider. 26 + google.protobuf.Timestamp after = 4; 27 + // Before is an optional parameter to specify the latest commit to consider. 28 + google.protobuf.Timestamp before = 5; 29 + // MaxCommits is an optional parameter to specify the maximum number of commits 30 + // to return. If max_commits is 0, all commits that match the criteria will be 31 + // returned. 32 + uint32 max_commits = 6; 33 + // Skip is an optional parameter to specify the number of commits to skip. 34 + // This can be used to implement a poor mans pagination. 35 + uint32 skip = 7; 36 + } 37 + message CommitLogResponse { 38 + repeated GitCommit commits = 1; 39 + } 40 + 41 + message GetBlobRequest { 42 + // repo carries the DID as a string. 43 + string repo = 1; 44 + // oid is the blob object id (hex). 45 + string oid = 2; 46 + } 47 + message BlobChunk { 48 + bytes data = 1; 49 + } 50 + 51 + message DiffRequest { 52 + // repo carries the DID as a string; parsing/validation is an impl detail. 53 + string repo = 1; 54 + // base_rev_spec/head_rev_spec are commit-ish ref strings. 55 + // base_rev_spec is optional; when unset, diff head against head's first parent. 56 + optional bytes base_rev_spec = 2; 57 + bytes head_rev_spec = 3; 58 + ComparisonType comparison_type = 4; 59 + 60 + enum ComparisonType { 61 + COMPARISON_TYPE_UNSPECIFIED = 0; 62 + // Corresponds to the BASE..HEAD syntax that only returns any commits that 63 + // are in HEAD but not in BASE. 64 + COMPARISON_TYPE_ONLY_IN_HEAD = 1; 65 + // Corresponds to the BASE...HEAD syntax that returns any commits that are 66 + // not in both BASE and HEAD. 67 + COMPARISON_TYPE_INTERSECTION = 2; 68 + } 69 + } 70 + 71 + message InterdiffRequest { 72 + // repo carries the DID as a string. 73 + string repo = 1; 74 + // Old patch range (from_base..from_head) and new patch range (to_base..to_head). 75 + bytes from_base = 2; 76 + bytes from_head = 3; 77 + bytes to_base = 4; 78 + bytes to_head = 5; 79 + } 80 + 81 + // Diff and Interdiff stream one FileDiff per changed file. 82 + 83 + message FileContent { 84 + string path = 1; 85 + string oid = 2; 86 + uint64 size = 3; 87 + bool is_binary = 4; 88 + bool is_submodule = 5; 89 + // Raw file bytes, inlined when the oid is not fetchable by the client 90 + // (e.g. interdiff) 91 + optional bytes content = 6; 92 + } 93 + 94 + // One aligned line pair; a side is absent (None) when unset. 95 + message LinePair { 96 + optional uint32 lhs = 1; 97 + optional uint32 rhs = 2; 98 + } 99 + 100 + message Hunk { 101 + // LineNumber (u32) sets containing novel content per side. 102 + repeated uint32 novel_lhs = 1; 103 + repeated uint32 novel_rhs = 2; 104 + repeated LinePair lines = 3; 105 + } 106 + 107 + // Number of bytes per side when the files differ (Rust Option<(usize, usize)>). 108 + message ByteChanges { 109 + uint64 lhs = 1; 110 + uint64 rhs = 2; 111 + } 112 + 113 + message FileDiff { 114 + FileContent lhs_src = 1; 115 + FileContent rhs_src = 2; 116 + repeated Hunk hunks = 3; 117 + optional ByteChanges has_byte_changes = 4; 118 + bool has_syntactic_changes = 5; 119 + // TODO: lhs_positions & rhs_positions 120 + } 121 + 122 + message GitCommit { 123 + string oid = 1; 124 + GitSignature author = 2; 125 + GitSignature committer = 3; 126 + bytes message = 4; 127 + repeated string parents = 5; 128 + map<string, string> extra_headers = 6; 129 + } 130 + 131 + message GitSignature { 132 + bytes name = 1; 133 + bytes email = 2; 134 + google.protobuf.Timestamp date = 3; 135 + }
+370
gitmirror/src/diff.rs
··· 1 + use gix::ObjectId; 2 + use gix::bstr::ByteSlice as _; 3 + use gix::objs::tree::EntryKind; 4 + use line_numbers::{LineNumber, SingleLineSpan}; 5 + use rustc_hash::FxHashSet; 6 + use tracing::info; 7 + 8 + /// Blobs larger than this are treated as binary. 9 + const LARGE_FILE_THRESHOLD_BYTES: u64 = 1024 * 1024; 10 + 11 + #[derive(Debug)] 12 + pub struct FileContent { 13 + pub(crate) path: String, 14 + pub(crate) oid: String, 15 + pub(crate) size: usize, 16 + pub(crate) is_binary: bool, 17 + pub(crate) is_submodule: bool, 18 + /// Raw file bytes, inlined when the `oid` is not fetchable by the client (interdiff's 19 + /// synthetic rebased tree). `None` for ordinary diffs and for binary/oversized blobs. 20 + pub(crate) content: Option<Vec<u8>>, 21 + } 22 + 23 + impl From<FileContent> for crate::protocol::v1::FileContent { 24 + fn from(f: FileContent) -> Self { 25 + Self { 26 + path: f.path, 27 + oid: f.oid, 28 + size: f.size as u64, 29 + is_binary: f.is_binary, 30 + is_submodule: f.is_submodule, 31 + content: f.content, 32 + } 33 + } 34 + } 35 + 36 + #[derive(Debug, Clone)] 37 + pub struct Hunk { 38 + pub(crate) novel_lhs: FxHashSet<LineNumber>, 39 + pub(crate) novel_rhs: FxHashSet<LineNumber>, 40 + pub(crate) lines: Vec<(Option<LineNumber>, Option<LineNumber>)>, 41 + } 42 + 43 + impl From<Hunk> for crate::protocol::v1::Hunk { 44 + fn from(h: Hunk) -> Self { 45 + // Sort the novel line sets for deterministic output. 46 + let sorted = |set: FxHashSet<LineNumber>| -> Vec<u32> { 47 + let mut v: Vec<u32> = set.into_iter().map(|n| n.0).collect(); 48 + v.sort_unstable(); 49 + v 50 + }; 51 + Self { 52 + novel_lhs: sorted(h.novel_lhs), 53 + novel_rhs: sorted(h.novel_rhs), 54 + lines: h 55 + .lines 56 + .into_iter() 57 + .map(|(lhs, rhs)| crate::protocol::v1::LinePair { 58 + lhs: lhs.map(|n| n.0), 59 + rhs: rhs.map(|n| n.0), 60 + }) 61 + .collect(), 62 + } 63 + } 64 + } 65 + 66 + /// A matched token (an atom, a delimiter, or a comment word). 67 + #[derive(PartialEq, Eq, Debug, Clone)] 68 + pub enum MatchKind { 69 + // TBD 70 + } 71 + 72 + #[derive(Debug, Clone, PartialEq, Eq)] 73 + pub struct MatchedPos { 74 + pub(crate) kind: MatchKind, 75 + pub(crate) pos: SingleLineSpan, 76 + } 77 + 78 + #[derive(Debug)] 79 + pub struct Diff { 80 + pub(crate) lhs_src: FileContent, 81 + pub(crate) rhs_src: FileContent, 82 + pub(crate) hunks: Vec<Hunk>, 83 + 84 + #[allow(unused)] 85 + pub(crate) lhs_positions: Vec<MatchedPos>, 86 + #[allow(unused)] 87 + pub(crate) rhs_positions: Vec<MatchedPos>, 88 + 89 + /// If the two files do not have exactly the same bytes, the 90 + /// number of bytes in each file. 91 + pub(crate) has_byte_changes: Option<(usize, usize)>, 92 + pub(crate) has_syntactic_changes: bool, 93 + } 94 + 95 + impl From<Diff> for crate::protocol::v1::FileDiff { 96 + fn from(d: Diff) -> Self { 97 + Self { 98 + lhs_src: Some(d.lhs_src.into()), 99 + rhs_src: Some(d.rhs_src.into()), 100 + hunks: d.hunks.into_iter().map(Into::into).collect(), 101 + has_byte_changes: d.has_byte_changes.map(|(lhs, rhs)| { 102 + crate::protocol::v1::ByteChanges { 103 + lhs: lhs as u64, 104 + rhs: rhs as u64, 105 + } 106 + }), 107 + has_syntactic_changes: d.has_syntactic_changes, 108 + } 109 + } 110 + } 111 + 112 + /// Diff two trees, yielding one [`Diff`] per changed file (line-level [`Hunk`]s included). 113 + /// 114 + /// Returns an iterator of `anyhow::Result<Diff>`: per-file diffing can fail independently, so 115 + /// each item is fallible. The consumer drives it lazily and can stop at any point by dropping 116 + /// the iterator (e.g. when the gRPC client hangs up). 117 + pub fn diff<'repo>( 118 + repo: &'repo gix::Repository, 119 + old_tree: &gix::Tree<'_>, 120 + new_tree: &gix::Tree<'_>, 121 + embed_content: bool, 122 + ) -> anyhow::Result<DiffIter<'repo>> { 123 + let changes = repo.diff_tree_to_tree(Some(old_tree), Some(new_tree), None)?; 124 + let mut cache = repo.diff_resource_cache_for_tree_diff()?; 125 + cache.filter.options.large_file_threshold_bytes = LARGE_FILE_THRESHOLD_BYTES; 126 + Ok(DiffIter { 127 + repo, 128 + changes: changes.into_iter(), 129 + cache, 130 + embed_content, 131 + }) 132 + } 133 + 134 + /// Lazy iterator over per-file [`Diff`]s. Created by [`diff`]. 135 + pub struct DiffIter<'repo> { 136 + repo: &'repo gix::Repository, 137 + changes: std::vec::IntoIter<gix::object::tree::diff::ChangeDetached>, 138 + cache: gix::diff::blob::Platform, 139 + embed_content: bool, 140 + } 141 + 142 + impl Iterator for DiffIter<'_> { 143 + type Item = anyhow::Result<Diff>; 144 + 145 + fn next(&mut self) -> Option<Self::Item> { 146 + loop { 147 + let change = self.changes.next()?; 148 + let (old, new) = change_sides(&change); 149 + // Trees are recursed into by gix and never diffed directly; skip defensively. 150 + if old.is_kind(EntryKind::Tree) || new.is_kind(EntryKind::Tree) { 151 + continue; 152 + } 153 + // Submodules (gitlinks) can't go through the blob pipeline — their commit lives in 154 + // another repo. Emit the commit oids directly for the caller to compare. 155 + if old.is_kind(EntryKind::Commit) || new.is_kind(EntryKind::Commit) { 156 + return Some(Ok(submodule_diff(self.repo, &change, old, new))); 157 + } 158 + let result = build_diff(self.repo, &change, &mut self.cache, self.embed_content); 159 + self.cache.clear_resource_cache_keep_allocation(); 160 + return Some(result); 161 + } 162 + } 163 + } 164 + 165 + /// One side (old or new) of a change. 166 + enum Side { 167 + Absent, 168 + Present { oid: ObjectId, kind: EntryKind }, 169 + } 170 + 171 + impl Side { 172 + fn is_kind(&self, wanted: EntryKind) -> bool { 173 + matches!(self, Side::Present { kind, .. } if *kind == wanted) 174 + } 175 + } 176 + 177 + /// Decompose a change into its `(old, new)` sides regardless of variant. 178 + fn change_sides(change: &gix::object::tree::diff::ChangeDetached) -> (Side, Side) { 179 + use gix::object::tree::diff::ChangeDetached as C; 180 + let present = |oid, mode: gix::object::tree::EntryMode| Side::Present { 181 + oid, 182 + kind: mode.kind(), 183 + }; 184 + match change { 185 + C::Addition { id, entry_mode, .. } => (Side::Absent, present(*id, *entry_mode)), 186 + C::Deletion { id, entry_mode, .. } => (present(*id, *entry_mode), Side::Absent), 187 + C::Modification { 188 + previous_id, 189 + previous_entry_mode, 190 + id, 191 + entry_mode, 192 + .. 193 + } => ( 194 + present(*previous_id, *previous_entry_mode), 195 + present(*id, *entry_mode), 196 + ), 197 + C::Rewrite { 198 + source_id, 199 + source_entry_mode, 200 + id, 201 + entry_mode, 202 + .. 203 + } => ( 204 + present(*source_id, *source_entry_mode), 205 + present(*id, *entry_mode), 206 + ), 207 + } 208 + } 209 + 210 + /// Build a [`Diff`] for a submodule (gitlink) change: no hunks, both sides carry their commit 211 + /// oid with `is_submodule` set. The caller compares the oids as submodule pointers. 212 + fn submodule_diff( 213 + repo: &gix::Repository, 214 + change: &gix::object::tree::diff::ChangeDetached, 215 + old: Side, 216 + new: Side, 217 + ) -> Diff { 218 + let path = change.location().to_string(); 219 + let side = |s: Side| FileContent { 220 + path: path.clone(), 221 + oid: match s { 222 + Side::Absent => ObjectId::null(repo.object_hash()).to_string(), 223 + Side::Present { oid, .. } => oid.to_string(), 224 + }, 225 + size: 0, 226 + is_binary: false, 227 + is_submodule: true, 228 + content: None, 229 + }; 230 + Diff { 231 + lhs_src: side(old), 232 + rhs_src: side(new), 233 + hunks: Vec::new(), 234 + lhs_positions: Vec::new(), 235 + rhs_positions: Vec::new(), 236 + has_byte_changes: None, 237 + has_syntactic_changes: false, 238 + } 239 + } 240 + 241 + /// Build the [`Diff`] for a single changed file. 242 + fn build_diff( 243 + repo: &gix::Repository, 244 + change: &gix::object::tree::diff::ChangeDetached, 245 + cache: &mut gix::diff::blob::Platform, 246 + embed_content: bool, 247 + ) -> anyhow::Result<Diff> { 248 + use gix::diff::blob::platform::prepare_diff::Operation; 249 + use gix::diff::blob::platform::resource::Data; 250 + use gix::diff::blob::{Diff as BlobDiff, InternedInput}; 251 + use gix::prelude::TreeDiffChangeExt as _; 252 + 253 + let change = change.attach(repo, repo); 254 + let blob = change.diff(cache)?; 255 + let out = blob.resource_cache.prepare_diff()?; 256 + 257 + // Per-side file metadata, derived from the prepared resources. 258 + let side = 259 + |res: &gix::diff::blob::platform::Resource<'_>, embed_content: bool| -> FileContent { 260 + let (size, is_binary, content) = match res.data { 261 + // Only textual buffers carry inlinable bytes; binary/missing sides fall back to oid. 262 + Data::Buffer { buf, .. } => (buf.len(), false, embed_content.then(|| buf.to_vec())), 263 + Data::Binary { size } => (size as usize, true, None), 264 + Data::Missing => (0, false, None), 265 + }; 266 + FileContent { 267 + path: res.rela_path.to_string(), 268 + oid: res.id.to_string(), 269 + size, 270 + is_binary, 271 + is_submodule: false, 272 + content, 273 + } 274 + }; 275 + let mut lhs_src = side(&out.old, embed_content); 276 + let mut rhs_src = side(&out.new, false); 277 + 278 + let has_byte_changes = if lhs_src.size == rhs_src.size && out.old.id == out.new.id { 279 + None 280 + } else { 281 + Some((lhs_src.size, rhs_src.size)) 282 + }; 283 + 284 + let hunks = match out.operation { 285 + Operation::InternalDiff { algorithm } => { 286 + let input = InternedInput::new(out.old.intern_source(), out.new.intern_source()); 287 + let mut d = BlobDiff::compute(algorithm, &input); 288 + d.postprocess_lines(&input); 289 + d.hunks() 290 + .map(|h| { 291 + let before: Vec<LineNumber> = h.before.clone().map(LineNumber).collect(); 292 + let after: Vec<LineNumber> = h.after.clone().map(LineNumber).collect(); 293 + let n = before.len().max(after.len()); 294 + let lines = (0..n) 295 + .map(|i| (before.get(i).copied(), after.get(i).copied())) 296 + .collect(); 297 + Hunk { 298 + novel_lhs: before.iter().copied().collect(), 299 + novel_rhs: after.iter().copied().collect(), 300 + lines, 301 + } 302 + }) 303 + .collect() 304 + } 305 + Operation::SourceOrDestinationIsBinary => { 306 + lhs_src.is_binary = true; 307 + rhs_src.is_binary = true; 308 + Vec::new() 309 + } 310 + Operation::ExternalCommand { .. } => unreachable!("we disabled that"), 311 + }; 312 + 313 + Ok(Diff { 314 + lhs_src, 315 + rhs_src, 316 + hunks, 317 + lhs_positions: Vec::new(), 318 + rhs_positions: Vec::new(), 319 + has_byte_changes, 320 + has_syntactic_changes: false, 321 + }) 322 + } 323 + 324 + /// Compute the two trees whose diff is the interdiff between an old patch 325 + /// version (`from_base..from_head`) and a new one (`to_base..to_head`). 326 + /// 327 + /// Rebase `from_base..from_head` onto `to_base` and return rebased tree so 328 + /// caller can diff between `rebased_tree` and `to_head.tree` 329 + pub fn prepare_interdiff<'repo>( 330 + repo: &'repo gix::Repository, 331 + (from_base_id, from_head_id): (ObjectId, ObjectId), 332 + to_base_id: ObjectId, 333 + ) -> anyhow::Result<gix::Tree<'repo>> { 334 + let from_head = repo.find_commit(from_head_id)?; 335 + 336 + let from_base = repo.find_commit(from_base_id)?; 337 + let to_base = repo.find_commit(to_base_id)?; 338 + 339 + // Endpoint trees for the 3-way merge. 340 + let from_base_tree = from_base.tree_id()?.detach(); 341 + let from_head_tree = from_head.tree_id()?.detach(); 342 + let to_base_tree = to_base.tree_id()?.detach(); 343 + 344 + // Rebase = replay (from_base_tree -> from_head_tree) onto to_base_tree: 345 + // ancestor = from_base_tree, ours = to_base_tree, theirs = from_head_tree. 346 + let options = repo.tree_merge_options()?; 347 + let labels = gix::merge::blob::builtin_driver::text::Labels { 348 + ancestor: Some("from.base".as_bytes().as_bstr()), 349 + current: Some("to.base".as_bytes().as_bstr()), 350 + other: Some("from.head".as_bytes().as_bstr()), 351 + }; 352 + let mut outcome = repo.merge_trees( 353 + from_base_tree, 354 + to_base_tree, 355 + from_head_tree, 356 + labels, 357 + options, 358 + )?; 359 + 360 + if !outcome.conflicts.is_empty() { 361 + info!( 362 + conflicts = outcome.conflicts.len(), 363 + "interdiff rebase produced conflicts; tree contains conflict markers" 364 + ); 365 + } 366 + 367 + let rebased_id = outcome.tree.write()?.detach(); 368 + let rebased_tree = repo.find_tree(rebased_id)?; 369 + Ok(rebased_tree) 370 + }
+45
gitmirror/src/main.rs
··· 1 + use std::net::SocketAddr; 2 + use std::path::PathBuf; 3 + 4 + use clap::{Parser, Subcommand}; 5 + 6 + mod diff; 7 + mod protocol; 8 + mod service; 9 + 10 + #[derive(Parser)] 11 + #[command(name = "gitmirror", about = "Git mirror gRPC service")] 12 + struct Cli { 13 + #[command(subcommand)] 14 + cmd: Command, 15 + } 16 + 17 + #[derive(Subcommand)] 18 + enum Command { 19 + /// Run the gRPC server. 20 + Serve(ServeArgs), 21 + } 22 + 23 + #[derive(clap::Args)] 24 + struct ServeArgs { 25 + /// Address to bind the gRPC server to. 26 + #[arg(long, env = "GITMIRROR_ADDR", default_value = "127.0.0.1:9000")] 27 + addr: SocketAddr, 28 + 29 + /// Base directory holding bare mirror repos, one per DID (<base>/<did>). 30 + #[arg(long, env = "GITMIRROR_REPO_BASE", default_value = "repos")] 31 + repo_base: PathBuf, 32 + } 33 + 34 + #[tokio::main] 35 + async fn main() -> anyhow::Result<()> { 36 + tracing_subscriber::fmt() 37 + .with_env_filter( 38 + tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()), 39 + ) 40 + .init(); 41 + 42 + match Cli::parse().cmd { 43 + Command::Serve(args) => service::serve(args.addr, args.repo_base).await, 44 + } 45 + }
+3
gitmirror/src/protocol.rs
··· 1 + pub mod v1 { 2 + tonic::include_proto!("gitmirror.v1"); 3 + }
+362
gitmirror/src/service.rs
··· 1 + use std::net::SocketAddr; 2 + use std::path::PathBuf; 3 + use std::pin::Pin; 4 + 5 + use gix::bstr::ByteSlice as _; 6 + use gix::revision::plumbing::Spec as RevSpec; 7 + use gix::revision::walk::Sorting; 8 + use tokio::sync::mpsc; 9 + use tokio_stream::Stream; 10 + use tokio_stream::wrappers::ReceiverStream; 11 + use tonic::transport::Server; 12 + use tonic::{Request, Response, Status}; 13 + use tracing::{debug, info}; 14 + 15 + use crate::diff::{self, prepare_interdiff}; 16 + use crate::protocol::v1::diff_request::ComparisonType; 17 + use crate::protocol::v1::git_mirror_service_server::{GitMirrorService, GitMirrorServiceServer}; 18 + use crate::protocol::v1::{ 19 + BlobChunk, CommitLogRequest, CommitLogResponse, DiffRequest, FileDiff, GetBlobRequest, 20 + GitCommit, GitSignature, InterdiffRequest, 21 + }; 22 + 23 + type FileDiffStream = Pin<Box<dyn Stream<Item = Result<FileDiff, Status>> + Send>>; 24 + type BlobChunkStream = Pin<Box<dyn Stream<Item = Result<BlobChunk, Status>> + Send>>; 25 + type CommitLogResponseStream = 26 + Pin<Box<dyn Stream<Item = Result<CommitLogResponse, Status>> + Send>>; 27 + 28 + /// Blob bytes are streamed in chunks of this size. 29 + const BLOB_CHUNK_SIZE: usize = 64 * 1024; 30 + /// GitCommits are streamed in batches of this size. 31 + const COMMIT_LOG_BATCH_SIZE: usize = 128; 32 + 33 + struct GitMirror { 34 + repo_base: PathBuf, 35 + } 36 + 37 + impl GitMirror { 38 + fn open_repo(&self, did: &str) -> Result<gix::Repository, Status> { 39 + if !did.starts_with("did:") { 40 + return Err(Status::invalid_argument("repo must be a DID")); 41 + } 42 + gix::open(self.repo_base.join(did)) 43 + .map_err(|e| Status::not_found(format!("repo not found: {e}"))) 44 + } 45 + } 46 + 47 + #[tonic::async_trait] 48 + impl GitMirrorService for GitMirror { 49 + type DiffStream = FileDiffStream; 50 + 51 + async fn diff( 52 + &self, 53 + request: Request<DiffRequest>, 54 + ) -> Result<Response<Self::DiffStream>, Status> { 55 + let req = request.into_inner(); 56 + let repo = self.open_repo(&req.repo)?; 57 + // Resolve refs up-front so bad input surfaces as the RPC status, then move the 58 + // owned repo + oids into a blocking task for the (synchronous) diff loop. 59 + let base_oid = req 60 + .base_rev_spec 61 + .as_deref() 62 + .map(|b| resolve_commit_oid(&repo, b)) 63 + .transpose()?; 64 + let head_oid = resolve_commit_oid(&repo, &req.head_rev_spec)?; 65 + let comparison_type = 66 + ComparisonType::try_from(req.comparison_type).unwrap_or(ComparisonType::Unspecified); 67 + let safe = repo.into_sync(); 68 + 69 + let (tx, rx) = mpsc::channel::<Result<FileDiff, Status>>(16); 70 + tokio::task::spawn_blocking(move || { 71 + let repo = safe.to_thread_local(); 72 + 73 + let run = || -> anyhow::Result<()> { 74 + let head_commit = repo.find_commit(head_oid)?; 75 + let old = match base_oid { 76 + Some(base_oid) => match comparison_type { 77 + ComparisonType::OnlyInHead => { 78 + repo.find_tree(repo.find_commit(base_oid)?.tree_id()?)? 79 + } 80 + ComparisonType::Unspecified | ComparisonType::Intersection => { 81 + let merge_base = repo.merge_base(base_oid, head_oid)?.detach(); 82 + repo.find_tree(repo.find_commit(merge_base)?.tree_id()?)? 83 + } 84 + }, 85 + None => match head_commit.parent_ids().next() { 86 + Some(parent_id) => { 87 + repo.find_tree(repo.find_commit(parent_id.detach())?.tree_id()?)? 88 + } 89 + None => repo.empty_tree(), 90 + }, 91 + }; 92 + let new = repo.find_tree(head_commit.tree_id()?)?; 93 + for item in diff::diff(&repo, &old, &new, false)? { 94 + if tx.blocking_send(Ok(item?.into())).is_err() { 95 + break; // client hung up 96 + } 97 + } 98 + Ok(()) 99 + }; 100 + if let Err(e) = run() { 101 + let _ = tx.blocking_send(Err(Status::internal(e.to_string()))); 102 + } 103 + }); 104 + 105 + Ok(Response::new(Box::pin(ReceiverStream::new(rx)))) 106 + } 107 + 108 + type InterdiffStream = FileDiffStream; 109 + 110 + async fn interdiff( 111 + &self, 112 + request: Request<InterdiffRequest>, 113 + ) -> Result<Response<Self::InterdiffStream>, Status> { 114 + let req = request.into_inner(); 115 + let repo = self.open_repo(&req.repo)?; 116 + let from_base_id = resolve_commit_oid(&repo, &req.from_base)?; 117 + let from_head_id = resolve_commit_oid(&repo, &req.from_head)?; 118 + let to_base_id = resolve_commit_oid(&repo, &req.to_base)?; 119 + let to_head_id = resolve_commit_oid(&repo, &req.to_head)?; 120 + let safe = repo.into_sync(); 121 + 122 + let (tx, rx) = mpsc::channel::<Result<FileDiff, Status>>(16); 123 + tokio::task::spawn_blocking(move || { 124 + let repo = safe.to_thread_local(); 125 + let run = || -> anyhow::Result<()> { 126 + let to_head = repo.find_commit(to_head_id)?; 127 + let to_head_tree = to_head.tree()?; 128 + let rebased_tree = 129 + prepare_interdiff(&repo, (from_base_id, from_head_id), to_base_id)?; 130 + for item in diff::diff(&repo, &rebased_tree, &to_head_tree, true)? { 131 + if tx.blocking_send(Ok(item?.into())).is_err() { 132 + break; // client hung up 133 + } 134 + } 135 + Ok(()) 136 + }; 137 + if let Err(e) = run() { 138 + let _ = tx.blocking_send(Err(Status::internal(e.to_string()))); 139 + } 140 + }); 141 + 142 + Ok(Response::new(Box::pin(ReceiverStream::new(rx)))) 143 + } 144 + 145 + type GetBlobStream = BlobChunkStream; 146 + 147 + async fn get_blob( 148 + &self, 149 + request: Request<GetBlobRequest>, 150 + ) -> Result<Response<Self::GetBlobStream>, Status> { 151 + let req = request.into_inner(); 152 + let repo = self.open_repo(&req.repo)?; 153 + let oid = gix::ObjectId::from_hex(req.oid.as_bytes()) 154 + .map_err(|e| Status::invalid_argument(format!("bad oid '{}': {e}", req.oid)))?; 155 + let safe = repo.into_sync(); 156 + 157 + let (tx, rx) = mpsc::channel::<Result<BlobChunk, Status>>(16); 158 + tokio::task::spawn_blocking(move || { 159 + let repo = safe.to_thread_local(); 160 + let run = || -> anyhow::Result<()> { 161 + let blob = repo.find_object(oid)?.try_into_blob()?; 162 + for chunk in blob.data.chunks(BLOB_CHUNK_SIZE) { 163 + let msg = BlobChunk { 164 + data: chunk.to_vec(), 165 + }; 166 + if tx.blocking_send(Ok(msg)).is_err() { 167 + break; // client hung up 168 + } 169 + } 170 + Ok(()) 171 + }; 172 + if let Err(e) = run() { 173 + let _ = tx.blocking_send(Err(Status::internal(e.to_string()))); 174 + } 175 + }); 176 + 177 + Ok(Response::new(Box::pin(ReceiverStream::new(rx)))) 178 + } 179 + 180 + type CommitLogStream = CommitLogResponseStream; 181 + 182 + async fn commit_log( 183 + &self, 184 + request: Request<CommitLogRequest>, 185 + ) -> Result<Response<Self::CommitLogStream>, Status> { 186 + let req = request.into_inner(); 187 + debug!( 188 + repo = %req.repo, 189 + all_refs = req.all_refs, 190 + ranges = ?req.ranges, 191 + after = ?req.after, 192 + before = ?req.before, 193 + max_commits = req.max_commits, 194 + skip = req.skip, 195 + "commit_log request", 196 + ); 197 + if req.all_refs != req.ranges.is_empty() { 198 + return Err(Status::invalid_argument( 199 + "specify exactly one of `ranges` or `all_refs`", 200 + )); 201 + } 202 + let repo = self.open_repo(&req.repo)?; 203 + let safe = repo.into_sync(); 204 + 205 + let (tx, rx) = mpsc::channel::<Result<CommitLogResponse, Status>>(16); 206 + tokio::task::spawn_blocking(move || { 207 + let repo = safe.to_thread_local(); 208 + let run = || -> anyhow::Result<()> { 209 + let after = req.after.map(|t| t.seconds); 210 + let before = req.before.map(|t| t.seconds); 211 + let max_commits = req.max_commits as usize; 212 + let mut skip = req.skip as usize; 213 + let mut sent = 0usize; 214 + let mut batch = Vec::with_capacity(COMMIT_LOG_BATCH_SIZE); 215 + 216 + for info in commit_log_walk(&repo, &req)? { 217 + let info = info?; 218 + let commit_time = info.commit_time(); 219 + if before.is_some_and(|b| commit_time > b) { 220 + continue; 221 + } 222 + if after.is_some_and(|a| commit_time < a) { 223 + break; // newest-first order: nothing older will match either 224 + } 225 + if skip > 0 { 226 + skip -= 1; 227 + continue; 228 + } 229 + if max_commits != 0 && sent >= max_commits { 230 + break; 231 + } 232 + batch.push(GitCommit::try_from(&info.object()?)?); 233 + sent += 1; 234 + if batch.len() == COMMIT_LOG_BATCH_SIZE { 235 + let msg = CommitLogResponse { 236 + commits: std::mem::take(&mut batch), 237 + }; 238 + if tx.blocking_send(Ok(msg)).is_err() { 239 + return Ok(()); // client hung up 240 + } 241 + } 242 + } 243 + if !batch.is_empty() { 244 + let _ = tx.blocking_send(Ok(CommitLogResponse { commits: batch })); 245 + } 246 + Ok(()) 247 + }; 248 + if let Err(e) = run() { 249 + let _ = tx.blocking_send(Err(Status::internal(e.to_string()))); 250 + } 251 + }); 252 + 253 + Ok(Response::new(Box::pin(ReceiverStream::new(rx)))) 254 + } 255 + } 256 + 257 + /// Resolve a commit-ish ref string (oid, short oid, branch/tag) to its commit oid. 258 + fn resolve_commit_oid(repo: &gix::Repository, spec: &[u8]) -> Result<gix::ObjectId, Status> { 259 + let commit = repo 260 + .rev_parse_single(spec.as_bstr()) 261 + .map_err(|e| { 262 + Status::invalid_argument(format!("bad rev '{}': {e}", String::from_utf8_lossy(spec))) 263 + })? 264 + .object() 265 + .map_err(|e| Status::internal(e.to_string()))? 266 + .peel_to_commit() 267 + .map_err(|e| Status::internal(e.to_string()))?; 268 + Ok(commit.id) 269 + } 270 + 271 + /// Resolve tips/hidden commits from a [`CommitLogRequest`] and return the resulting gix walk, 272 + /// sorted newest-first to match `git log`'s default order. 273 + fn commit_log_walk<'repo>( 274 + repo: &'repo gix::Repository, 275 + req: &CommitLogRequest, 276 + ) -> anyhow::Result<gix::revision::Walk<'repo>> { 277 + let mut tips = Vec::new(); 278 + let mut hidden = Vec::new(); 279 + 280 + if req.all_refs { 281 + for r in repo.references()?.all()? { 282 + let mut r = r.map_err(|e| anyhow::anyhow!(e))?; 283 + if let Ok(commit) = r.peel_to_commit() { 284 + tips.push(commit.id); 285 + } 286 + } 287 + } else { 288 + for range in &req.ranges { 289 + let revspec = repo.rev_parse(range.as_bstr())?; 290 + let spec = revspec.detach(); 291 + match spec { 292 + RevSpec::Include(id) => tips.push(id), 293 + RevSpec::Range { from, to } => { 294 + tips.push(to); 295 + hidden.push(from); 296 + } 297 + _ => { 298 + anyhow::bail!("The spec isn't currently supported: {spec:?}") 299 + } 300 + } 301 + } 302 + } 303 + 304 + Ok(repo 305 + .rev_walk(tips) 306 + .sorting(Sorting::ByCommitTime(Default::default())) 307 + .with_hidden(hidden) 308 + .all()?) 309 + } 310 + 311 + impl TryFrom<&gix::Commit<'_>> for GitCommit { 312 + type Error = anyhow::Error; 313 + 314 + fn try_from(commit: &gix::Commit<'_>) -> anyhow::Result<Self> { 315 + let decoded = commit.decode()?; 316 + Ok(GitCommit { 317 + oid: commit.id.to_string(), 318 + author: Some(decoded.author()?.try_into()?), 319 + committer: Some(decoded.committer()?.try_into()?), 320 + message: decoded.message.to_vec(), 321 + parents: decoded 322 + .parents 323 + .into_iter() 324 + .map(|id| id.to_string()) 325 + .collect(), 326 + extra_headers: decoded 327 + .extra_headers 328 + .iter() 329 + .map(|(k, v)| (k.to_string(), v.to_string())) 330 + .collect(), 331 + }) 332 + } 333 + } 334 + 335 + impl TryFrom<gix::actor::SignatureRef<'_>> for GitSignature { 336 + type Error = anyhow::Error; 337 + 338 + fn try_from(sig: gix::actor::SignatureRef<'_>) -> anyhow::Result<Self> { 339 + let time = sig.time()?; 340 + Ok(GitSignature { 341 + name: sig.name.to_vec(), 342 + email: sig.email.to_vec(), 343 + date: Some(prost_types::Timestamp { 344 + seconds: time.seconds, 345 + nanos: 0, 346 + }), 347 + }) 348 + } 349 + } 350 + 351 + /// Build the gRPC service and serve it until the process is stopped. 352 + pub async fn serve(addr: SocketAddr, repo_base: PathBuf) -> anyhow::Result<()> { 353 + let service = GitMirror { repo_base }; 354 + info!(addr = %addr, "gitmirror gRPC server listening"); 355 + 356 + Server::builder() 357 + .add_service(GitMirrorServiceServer::new(service)) 358 + .serve(addr) 359 + .await?; 360 + 361 + Ok(()) 362 + }
+10
localinfra/Caddyfile
··· 53 53 reverse_proxy knotmirror:7000 54 54 } 55 55 56 + gitmirror.tngl.boltless.dev { 57 + tls internal 58 + # gitmirror (tonic) serves h2c; Caddy defaults to HTTP/1.1 to the backend. 59 + reverse_proxy gitmirror:9000 { 60 + transport http { 61 + versions h2c 2 62 + } 63 + } 64 + } 65 + 56 66 # zoekt (internal service) 57 67 zoekt.tngl.boltless.dev { 58 68 tls internal
+29
localinfra/gitmirror.Dockerfile
··· 1 + # Development only. Not for production use. 2 + 3 + FROM rust:1.96-bookworm AS build 4 + 5 + RUN apt-get update && apt-get install -y --no-install-recommends protobuf-compiler libprotobuf-dev \ 6 + && rm -rf /var/lib/apt/lists/* 7 + 8 + WORKDIR /src 9 + COPY . . 10 + 11 + # Cache mounts on the cargo registry + target dir. The binary is copied out within the same 12 + # RUN because the target cache mount is unmounted afterwards (a later COPY --from could not 13 + # see it). 14 + RUN --mount=type=cache,target=/usr/local/cargo/registry \ 15 + --mount=type=cache,target=/src/target \ 16 + cargo build --release -p gitmirror \ 17 + && cp /src/target/release/gitmirror /usr/local/bin/gitmirror 18 + 19 + FROM debian:bookworm-slim 20 + 21 + RUN apt-get update && apt-get install -y --no-install-recommends git ca-certificates tini \ 22 + && rm -rf /var/lib/apt/lists/* 23 + 24 + COPY --from=build /usr/local/bin/gitmirror /usr/local/bin/gitmirror 25 + 26 + EXPOSE 9000 27 + 28 + ENTRYPOINT ["/usr/bin/tini", "--"] 29 + CMD ["sh", "-c", "if [ -f /usr/local/share/ca-certificates/caddy.crt ]; then update-ca-certificates; fi && exec /usr/local/bin/gitmirror serve"]