From f394dc9e6e1c4656e6063881264dba457228dda3 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 25 Oct 2023 12:48:23 -0700 Subject: [PATCH 01/18] Add GitHub actions --- .github/workflows/tests.yml | 38 +++++++++++++++++++++++++++++++++++++ go.mod | 2 +- 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/tests.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..e57926a --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,38 @@ +name: tests + +on: + pull_request: + push: + +jobs: + update: + name: Run tests + runs-on: ubuntu-latest + steps: + - + name: Install libgit2-dev + run: sudo apt-get install -y libgit2-dev + - + name: Checkout + uses: actions/checkout@v3 + - + name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: '^1.21.1' + - uses: actions/cache@v3 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + - + name: Set the right libgit2 version + run: | + sed -i -e 's/v34/v31/g' go.mod splitter/*.go + go mod tidy + - + name: Test + run: go test -v ./... diff --git a/go.mod b/go.mod index e951f5a..cdfc3e9 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/splitsh/lite -go 1.17 +go 1.21 require ( github.com/boltdb/bolt v1.3.1 From f2d9253550ae2e05a4d18f3a1abc310717a79b73 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 25 Oct 2023 18:09:24 -0700 Subject: [PATCH 02/18] Add more detail about how to compile the binary --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b961d50..eed11bb 100644 --- a/README.md +++ b/README.md @@ -43,8 +43,12 @@ choice. If you get version `1.5`, jump to the compilation step below. If not, you first need to change the version used in the code. Using the table on the [libgit2](https://github.com/libgit2/git2go#which-go-version-to-use) -repository, figure out which version you need. Then, replace the `v34` in the -`go.mod` file and in all files under the `splitter/` directory. Run `go mod tidy`. +repository, figure out which version you need. Lets say you need version `v31`: + +```bash +sed -i -e 's/v34/v31/g' go.mod splitter/*.go +go mod tidy +``` Then, compile `splitsh-lite`: @@ -137,9 +141,6 @@ Available options: * `--progress` displays a progress bar; - * `--quiet` suppresses all output on stderr (useful when run from an automated - script); - * `--scratch` flushes the cache (useful when a branch is force pushed or in case of a cache corruption). From 08804f1e8972c4264b037ce60c78d8e82589b11d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 29 Oct 2023 16:02:40 -0700 Subject: [PATCH 03/18] Tweak README --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index eed11bb..52a5c3a 100644 --- a/README.md +++ b/README.md @@ -40,10 +40,12 @@ Manual Installation First, you need to install `libgit2`, preferably using your package manager of choice. -If you get version `1.5`, jump to the compilation step below. If not, you first -need to change the version used in the code. Using the table on the -[libgit2](https://github.com/libgit2/git2go#which-go-version-to-use) -repository, figure out which version you need. Lets say you need version `v31`: +If you get `libgit2` version `1.5`, you're all set and jump to the compilation +step below. If not, you first need to change the `git2go` version used in the +code. Using the table on the +[libgit2](https://github.com/libgit2/git2go#which-go-version-to-use) repository, +figure out which version of the `git2go` you need based on the `liggit2` library +you installed. Let's say you need version `v31`: ```bash sed -i -e 's/v34/v31/g' go.mod splitter/*.go From 6cdc0a4137f805f85c4394e54ef6551e9670c641 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 1 Mar 2024 19:22:35 +0100 Subject: [PATCH 04/18] Fix CHANGELOG --- CHANGELOG | 3 +-- LICENSE | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 912cdb9..00f03c2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,12 +1,11 @@ CHANGELOG ========= -* 2.0.0 (2023-XX-XX) +* 2.0.0 (2023-10-25) * move to go.mod * remove the `--quiet` option (append `2>/dev/null` to the command instead) * remove the `--legacy` option (same as `--git '<1.8.2'`) - * move information console display to stderr instead of stdout * 1.0.1 (2017-02-24) diff --git a/LICENSE b/LICENSE index 4cd8bdd..d668879 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2019 Fabien Potencier +Copyright (c) 2015-2024 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From f19d527a89cfe864155815db1ac4109dc724dea1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 1 Mar 2024 19:35:06 +0100 Subject: [PATCH 05/18] Use bbolt as boltdb is not maintained anymore --- go.mod | 2 +- go.sum | 46 ++++++++++++---------------------------------- splitter/cache.go | 2 +- splitter/config.go | 2 +- 4 files changed, 15 insertions(+), 37 deletions(-) diff --git a/go.mod b/go.mod index cdfc3e9..0d79571 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/splitsh/lite go 1.21 require ( - github.com/boltdb/bolt v1.3.1 github.com/libgit2/git2go/v34 v34.0.0 + go.etcd.io/bbolt v1.3.9 ) require ( diff --git a/go.sum b/go.sum index 293631d..3741b9a 100644 --- a/go.sum +++ b/go.sum @@ -1,52 +1,30 @@ -github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/libgit2/git2go/v34 v34.0.0 h1:UKoUaKLmiCRbOCD3PtUi2hD6hESSXzME/9OUZrGcgu8= github.com/libgit2/git2go/v34 v34.0.0/go.mod h1:blVco2jDAw6YTXkErMMqzHLcAjKkwF0aWIRHBqiJkZ0= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= +go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/splitter/cache.go b/splitter/cache.go index 10ef216..ab64cc5 100644 --- a/splitter/cache.go +++ b/splitter/cache.go @@ -8,8 +8,8 @@ import ( "strconv" "time" - "github.com/boltdb/bolt" git "github.com/libgit2/git2go/v34" + bolt "go.etcd.io/bbolt" ) type cache struct { diff --git a/splitter/config.go b/splitter/config.go index bd0c734..7dcec5c 100644 --- a/splitter/config.go +++ b/splitter/config.go @@ -5,8 +5,8 @@ import ( "log" "sync" - "github.com/boltdb/bolt" git "github.com/libgit2/git2go/v34" + bolt "go.etcd.io/bbolt" ) // Prefix represents which paths to split From 336cb150a83d6f580b9fa5adbeff936a845b90e9 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 1 Mar 2024 20:15:34 +0100 Subject: [PATCH 06/18] Bump to Go 1.22 and update deps --- .github/workflows/tests.yml | 2 +- go.mod | 6 +++--- go.sum | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e57926a..396fc83 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,7 +19,7 @@ jobs: name: Set up Go uses: actions/setup-go@v3 with: - go-version: '^1.21.1' + go-version: '^1.22.0' - uses: actions/cache@v3 with: path: | diff --git a/go.mod b/go.mod index 0d79571..9424c21 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/splitsh/lite -go 1.21 +go 1.22 require ( github.com/libgit2/git2go/v34 v34.0.0 @@ -8,6 +8,6 @@ require ( ) require ( - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/sys v0.13.0 // indirect + golang.org/x/crypto v0.20.0 // indirect + golang.org/x/sys v0.17.0 // indirect ) diff --git a/go.sum b/go.sum index 3741b9a..9e563e5 100644 --- a/go.sum +++ b/go.sum @@ -12,19 +12,19 @@ go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg= +golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From d1ff5e1dc92216cbaacd918187780000c7ef0348 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 2 Mar 2024 09:40:11 +0100 Subject: [PATCH 07/18] Add vendor to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e165e44..fddd6f4 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ splitter-lite-tests/ +vendor/ From 5d55360bed6c29fb935c4e6294292878b9500347 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 6 Mar 2024 08:36:31 +0100 Subject: [PATCH 08/18] Remove unneeded argument --- splitter/state.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/splitter/state.go b/splitter/state.go index 20a3af2..5170735 100644 --- a/splitter/state.go +++ b/splitter/state.go @@ -257,7 +257,7 @@ func (s *state) subtreeForCommit(commit *git.Commit) (*git.Tree, error) { return s.treeByPath(tree, s.simplePrefix) } - return s.treeByPaths(tree, s.config.Prefixes) + return s.treeByPaths(tree) } func (s *state) treeByPath(tree *git.Tree, prefix string) (*git.Tree, error) { @@ -274,7 +274,7 @@ func (s *state) treeByPath(tree *git.Tree, prefix string) (*git.Tree, error) { return s.repo.LookupTree(treeEntry.Id) } -func (s *state) treeByPaths(tree *git.Tree, prefixes []*Prefix) (*git.Tree, error) { +func (s *state) treeByPaths(tree *git.Tree) (*git.Tree, error) { var currentTree, prefixedTree, mergedTree *git.Tree for _, prefix := range s.config.Prefixes { // splitting From 26da73eea4f58da4939279438743cb4d8aba6bb5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 6 Mar 2024 09:44:45 +0100 Subject: [PATCH 09/18] Sync DB only at the end of splits --- splitter/cache.go | 62 +++++++++++++++++++++++++++++------------------ splitter/state.go | 4 +-- 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/splitter/cache.go b/splitter/cache.go index ab64cc5..9818d12 100644 --- a/splitter/cache.go +++ b/splitter/cache.go @@ -16,6 +16,7 @@ type cache struct { key []byte branch string db *bolt.DB + data map[string][]byte } func newCache(branch string, config *Config) (*cache, error) { @@ -32,6 +33,7 @@ func newCache(branch string, config *Config) (*cache, error) { db: db, branch: branch, key: key(config), + data: make(map[string][]byte), } err = db.Update(func(tx *bolt.Tx) error { @@ -46,6 +48,18 @@ func newCache(branch string, config *Config) (*cache, error) { } func (c *cache) close() error { + err := c.db.Update(func(tx *bolt.Tx) error { + for k, v := range c.data { + if err := tx.Bucket(c.key).Put([]byte(k), v); err != nil { + return err + } + } + return nil + }) + if err != nil { + return err + } + return c.db.Close() } @@ -68,17 +82,20 @@ func key(config *Config) []byte { return h.Sum(nil) } -func (c *cache) setHead(head *git.Oid) error { - return c.db.Update(func(tx *bolt.Tx) error { - return tx.Bucket(c.key).Put([]byte("head/"+c.branch), head[0:20]) - }) +func (c *cache) setHead(head *git.Oid) { + c.data["head/"+c.branch] = head[0:20] } func (c *cache) getHead() *git.Oid { + if head, ok := c.data["head"+c.branch]; ok { + return git.NewOidFromBytes(head) + } + var oid *git.Oid c.db.View(func(tx *bolt.Tx) error { result := tx.Bucket(c.key).Get([]byte("head/" + c.branch)) if result != nil { + c.data["head/"+c.branch] = result oid = git.NewOidFromBytes(result) } return nil @@ -87,10 +104,15 @@ func (c *cache) getHead() *git.Oid { } func (c *cache) get(rev *git.Oid) *git.Oid { + if v, ok := c.data[string(rev[0:20])]; ok { + return git.NewOidFromBytes(v) + } + var oid *git.Oid c.db.View(func(tx *bolt.Tx) error { result := tx.Bucket(c.key).Get(rev[0:20]) if result != nil { + c.data[string(rev[0:20])] = result oid = git.NewOidFromBytes(result) } return nil @@ -98,38 +120,32 @@ func (c *cache) get(rev *git.Oid) *git.Oid { return oid } -func (c *cache) set(rev, newrev *git.Oid, created bool) error { - return c.db.Update(func(tx *bolt.Tx) error { - err := tx.Bucket(c.key).Put(rev[0:20], newrev[0:20]) - if err != nil { - return err - } - - postfix := "/newest" - if created { - postfix = "/oldest" - } - - key := append(newrev[0:20], []byte(postfix)...) - return tx.Bucket(c.key).Put(key, rev[0:20]) - }) +func (c *cache) set(rev, newrev *git.Oid, created bool) { + c.data[string(rev[0:20])] = newrev[0:20] + postfix := "/newest" + if created { + postfix = "/oldest" + } + c.data[string(append(newrev[0:20], []byte(postfix)...))] = rev[0:20] } func (c *cache) gets(commits []*git.Oid) []*git.Oid { var oids []*git.Oid - c.db.View(func(tx *bolt.Tx) error { b := tx.Bucket(c.key) for _, commit := range commits { - result := b.Get(commit[0:20]) + result := c.data[string(commit[0:20])] if result != nil { oids = append(oids, git.NewOidFromBytes(result)) + } else { + result := b.Get(commit[0:20]) + if result != nil { + oids = append(oids, git.NewOidFromBytes(result)) + } } } - return nil }) - return oids } diff --git a/splitter/state.go b/splitter/state.go index 5170735..f14308f 100644 --- a/splitter/state.go +++ b/splitter/state.go @@ -239,9 +239,7 @@ func (s *state) splitRev(rev *git.Commit) (*git.Oid, error) { s.result.incCreated() } - if err := s.cache.set(rev.Id(), newrev, created); err != nil { - return nil, err - } + s.cache.set(rev.Id(), newrev, created) return newrev, nil } From e6d25ea8217c4f0e48af7a59421c068f17b7f8bf Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 7 Mar 2024 15:03:42 +0100 Subject: [PATCH 10/18] Remove dead code --- splitter/cache.go | 7 +------ splitter/state.go | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/splitter/cache.go b/splitter/cache.go index 9818d12..507c738 100644 --- a/splitter/cache.go +++ b/splitter/cache.go @@ -120,13 +120,8 @@ func (c *cache) get(rev *git.Oid) *git.Oid { return oid } -func (c *cache) set(rev, newrev *git.Oid, created bool) { +func (c *cache) set(rev, newrev *git.Oid) { c.data[string(rev[0:20])] = newrev[0:20] - postfix := "/newest" - if created { - postfix = "/oldest" - } - c.data[string(append(newrev[0:20], []byte(postfix)...))] = rev[0:20] } func (c *cache) gets(commits []*git.Oid) []*git.Oid { diff --git a/splitter/state.go b/splitter/state.go index f14308f..cd80647 100644 --- a/splitter/state.go +++ b/splitter/state.go @@ -239,7 +239,7 @@ func (s *state) splitRev(rev *git.Commit) (*git.Oid, error) { s.result.incCreated() } - s.cache.set(rev.Id(), newrev, created) + s.cache.set(rev.Id(), newrev) return newrev, nil } From 8f693c4bc23c8ea0de1c8ec1c421100a084c8b54 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 7 Mar 2024 15:26:05 +0100 Subject: [PATCH 11/18] Fix a few lint issues --- main.go | 2 +- splitter/cache.go | 2 +- splitter/config.go | 18 +++++++++++++----- splitter/result.go | 6 +++--- splitter/state.go | 18 +++++++++--------- splitter/utils.go | 2 +- 6 files changed, 28 insertions(+), 20 deletions(-) diff --git a/main.go b/main.go index aad01df..bbd9a61 100644 --- a/main.go +++ b/main.go @@ -32,7 +32,7 @@ func (p *prefixesFlag) Set(value string) error { for _, prefix := range []*splitter.Prefix(*p) { // FIXME: to should be normalized (xxx vs xxx/ for instance) if prefix.To == to { - return fmt.Errorf("Cannot have two prefix splits under the same directory: %s -> %s vs %s -> %s", prefix.From, prefix.To, from, to) + return fmt.Errorf("cannot have two prefix splits under the same directory: %s -> %s vs %s -> %s", prefix.From, prefix.To, from, to) } } diff --git a/splitter/cache.go b/splitter/cache.go index 507c738..60b1ac4 100644 --- a/splitter/cache.go +++ b/splitter/cache.go @@ -41,7 +41,7 @@ func newCache(branch string, config *Config) (*cache, error) { return err1 }) if err != nil { - return nil, fmt.Errorf("Impossible to create bucket: %s", err) + return nil, fmt.Errorf("impossible to create bucket: %s", err) } return c, nil diff --git a/splitter/config.go b/splitter/config.go index 7dcec5c..3448daa 100644 --- a/splitter/config.go +++ b/splitter/config.go @@ -53,17 +53,25 @@ func Split(config *Config, result *Result) error { // Validate validates the configuration func (config *Config) Validate() error { - if !git.ReferenceIsValidName(config.Origin) { - return fmt.Errorf("The origin is not a valid Git reference") + ok, err := git.ReferenceNameIsValid(config.Origin) + if err != nil { + return err + } + if !ok { + return fmt.Errorf("the origin is not a valid Git reference") } - if config.Target != "" && !git.ReferenceIsValidName(config.Target) { - return fmt.Errorf("The target is not a valid Git reference") + ok, err = git.ReferenceNameIsValid(config.Target) + if err != nil { + return err + } + if config.Target != "" && !ok { + return fmt.Errorf("the target is not a valid Git reference") } git, ok := supportedGitVersions[config.GitVersion] if !ok { - return fmt.Errorf(`The git version can only be one of "<1.8.2", "<2.8.0", or "latest"`) + return fmt.Errorf(`the git version can only be one of "<1.8.2", "<2.8.0", or "latest"`) } config.Git = git diff --git a/splitter/result.go b/splitter/result.go index ed99ecf..7dbcabc 100644 --- a/splitter/result.go +++ b/splitter/result.go @@ -84,12 +84,12 @@ func roundDuration(d, r time.Duration) time.Duration { } neg := d < 0 if neg { - d = -d + d -= d } if m := d % r; m+m < r { - d = d - m + d -= m } else { - d = d + r - m + d += r - m } if neg { return -d diff --git a/splitter/state.go b/splitter/state.go index cd80647..89a0fa5 100644 --- a/splitter/state.go +++ b/splitter/state.go @@ -119,7 +119,7 @@ func (s *state) split() error { revWalk, err := s.walker() if err != nil { - return fmt.Errorf("Impossible to walk the repository: %s", err) + return fmt.Errorf("impossible to walk the repository: %s", err) } defer revWalk.Free() @@ -163,12 +163,12 @@ func (s *state) split() error { func (s *state) walker() (*git.RevWalk, error) { revWalk, err := s.repo.Walk() if err != nil { - return nil, fmt.Errorf("Impossible to walk the repository: %s", err) + return nil, fmt.Errorf("impossible to walk the repository: %s", err) } err = s.pushRevs(revWalk) if err != nil { - return nil, fmt.Errorf("Impossible to determine split range: %s", err) + return nil, fmt.Errorf("impossible to determine split range: %s", err) } revWalk.Sorting(git.SortTopological | git.SortReverse) @@ -320,7 +320,7 @@ func (s *state) mergeTrees(t1, t2 *git.Tree) (*git.Tree, error) { defer index.Free() if index.HasConflicts() { - return nil, fmt.Errorf("Cannot split as there is a merge conflict between two paths") + return nil, fmt.Errorf("cannot split as there is a merge conflict between two paths") } oid, err := index.WriteTreeTo(s.repo) @@ -373,7 +373,7 @@ func (s *state) copyOrSkip(rev *git.Commit, tree *git.Tree, newParents []*git.Oi continue } - if 0 == ptree.Cmp(tree.Id()) { + if ptree.Cmp(tree.Id()) == 0 { // an identical parent could be used in place of this rev. identical = parent } else { @@ -384,7 +384,7 @@ func (s *state) copyOrSkip(rev *git.Commit, tree *git.Tree, newParents []*git.Oi // eliminate duplicates isNew := true for _, gp := range gotParents { - if 0 == gp.Cmp(parent) { + if gp.Cmp(parent) == 0 { isNew = false break } @@ -405,7 +405,7 @@ func (s *state) copyOrSkip(rev *git.Commit, tree *git.Tree, newParents []*git.Oi if s.config.Git > 2 && nil != identical && nil != nonIdentical { revWalk, err := s.repo.Walk() if err != nil { - return nil, false, fmt.Errorf("Impossible to walk the repository: %s", err) + return nil, false, fmt.Errorf("impossible to walk the repository: %s", err) } s.repoMu.Lock() @@ -413,7 +413,7 @@ func (s *state) copyOrSkip(rev *git.Commit, tree *git.Tree, newParents []*git.Oi err = revWalk.PushRange(fmt.Sprintf("%s..%s", identical, nonIdentical)) if err != nil { - return nil, false, fmt.Errorf("Impossible to determine split range: %s", err) + return nil, false, fmt.Errorf("impossible to determine split range: %s", err) } err = revWalk.Iterate(func(rev *git.Commit) bool { @@ -494,7 +494,7 @@ func (s *state) updateTarget() error { } if nil == s.result.Head() { - return fmt.Errorf("Unable to create branch %s as it is empty (no commits were split)", s.config.Target) + return fmt.Errorf("unable to create branch %s as it is empty (no commits were split)", s.config.Target) } obj, ref, err := s.repo.RevparseExt(s.config.Target) diff --git a/splitter/utils.go b/splitter/utils.go index 3c9249f..00328de 100644 --- a/splitter/utils.go +++ b/splitter/utils.go @@ -63,7 +63,7 @@ func normalizeOriginBranch(repo *git.Repository, origin string) (string, error) obj, ref, err := repo.RevparseExt(origin) if err != nil { - return "", fmt.Errorf("Bad revision for origin: %s", err) + return "", fmt.Errorf("bad revision for origin: %s", err) } if obj != nil { obj.Free() From a5c6982fcde43326e18393d279b1f0fdac814c0c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 7 Mar 2024 15:34:59 +0100 Subject: [PATCH 12/18] Use a more recent version of libgit2 --- .github/workflows/tests.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 396fc83..26d96b6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,8 +10,8 @@ jobs: runs-on: ubuntu-latest steps: - - name: Install libgit2-dev - run: sudo apt-get install -y libgit2-dev + name: Install deps + run: sudo apt-get install -y pkg-config cmake - name: Checkout uses: actions/checkout@v3 @@ -29,10 +29,14 @@ jobs: restore-keys: | ${{ runner.os }}-go- - - name: Set the right libgit2 version + name: Building run: | - sed -i -e 's/v34/v31/g' go.mod splitter/*.go - go mod tidy + go mod vendor + rm -rf vendor/github.com/libgit2/git2go + git clone https://github.com/libgit2/git2go vendor/github.com/libgit2/git2go/v34 + cd vendor/github.com/libgit2/git2go/v34 && git checkout v34.0.0 && git submodule update --init && make install-static - name: Test - run: go test -v ./... + run: | + export PKG_CONFIG_PATH=/home/runner/work/lite/lite/vendor/github.com/libgit2/git2go/v34/static-build/build + go test -v ./... From ca1a6cef4833abb991cee607c821b88762d23187 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 8 Mar 2024 08:09:53 +0100 Subject: [PATCH 13/18] Move head check for a more aggressive use of cache --- splitter/state.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/splitter/state.go b/splitter/state.go index 89a0fa5..124fd36 100644 --- a/splitter/state.go +++ b/splitter/state.go @@ -522,12 +522,18 @@ func (s *state) legacyMessage(rev *git.Commit) string { // pushRevs sets the range to split func (s *state) pushRevs(revWalk *git.RevWalk) error { - // this is needed as origin might be in the process of being updated by git.FetchOrigin() s.repoMu.Lock() defer s.repoMu.Unlock() - // find the latest split sha1 if any on origin var start *git.Oid + start = s.cache.getHead() + if start != nil { + s.result.moveHead(s.cache.get(start)) + // FIXME: CHECK that this is an ancestor of the branch? + return revWalk.PushRange(fmt.Sprintf("%s..%s", start, s.originBranch)) + } + + // find the latest split sha1 if any on origin var err error if s.config.Commit != "" { start, err = git.NewOid(s.config.Commit) @@ -538,13 +544,6 @@ func (s *state) pushRevs(revWalk *git.RevWalk) error { return revWalk.PushRange(fmt.Sprintf("%s^..%s", start, s.originBranch)) } - start = s.cache.getHead() - if start != nil { - s.result.moveHead(s.cache.get(start)) - // FIXME: CHECK that this is an ancestor of the branch? - return revWalk.PushRange(fmt.Sprintf("%s..%s", start, s.originBranch)) - } - branch, err := s.repo.RevparseSingle(s.originBranch) if err != nil { return err From 5dbf39b5b414c0bc0d1eb14eee66ce025626f9d3 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 8 Mar 2024 08:28:46 +0100 Subject: [PATCH 14/18] Add excluding directories support --- README.md | 16 +++++++++--- main.go | 10 +++++-- splitter/cache.go | 3 +++ splitter/config.go | 5 ++-- splitter/state.go | 65 +++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 88 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 52a5c3a..afe7814 100644 --- a/README.md +++ b/README.md @@ -128,10 +128,18 @@ splitsh-lite --prefix=lib/ --origin=origin/1.0 --path=/path/to/repo Available options: - * `--prefix` is the prefix of the directory to split; you can put the split - contents in a sub-directory of the target repository by using the - `--prefix=from:to` syntax; split several directories by passing multiple - `--prefix` flags; + * `--prefix` is the prefix of the directory to split; the value can be one of + the following: + + * `from`: the origin directory to split; + + * `from:to`: move the split content to a sub-directory on the target; + + * `from:to:exclude`: exclude a directory from the origin `from` directory + (use `from:to:exclude1:exclude2:...` to exclude more than one + directory). + + Split several directories by passing multiple `--prefix` flags; * `--path` is the path of the repository to split (current directory by default); diff --git a/main.go b/main.go index bbd9a61..ea79764 100644 --- a/main.go +++ b/main.go @@ -24,8 +24,14 @@ func (p *prefixesFlag) Set(value string) error { parts := strings.Split(value, ":") from := parts[0] to := "" - if len(parts) > 1 { + excludes := make([]string, 0) + if len(parts) >= 2 { to = parts[1] + if len(parts) > 2 { + for _, exclude := range parts[2:] { + excludes = append(excludes, exclude) + } + } } // value must be unique @@ -36,7 +42,7 @@ func (p *prefixesFlag) Set(value string) error { } } - *p = append(*p, &splitter.Prefix{From: from, To: to}) + *p = append(*p, &splitter.Prefix{From: from, To: to, Excludes: excludes}) return nil } diff --git a/splitter/cache.go b/splitter/cache.go index 60b1ac4..fca8953 100644 --- a/splitter/cache.go +++ b/splitter/cache.go @@ -77,6 +77,9 @@ func key(config *Config) []byte { for _, prefix := range config.Prefixes { io.WriteString(h, prefix.From) io.WriteString(h, prefix.To) + for _, exclude := range prefix.Excludes { + io.WriteString(h, exclude) + } } return h.Sum(nil) diff --git a/splitter/config.go b/splitter/config.go index 3448daa..7a4a0ef 100644 --- a/splitter/config.go +++ b/splitter/config.go @@ -11,8 +11,9 @@ import ( // Prefix represents which paths to split type Prefix struct { - From string - To string + From string + To string + Excludes []string } // Config represents a split configuration diff --git a/splitter/state.go b/splitter/state.go index 124fd36..7cdc417 100644 --- a/splitter/state.go +++ b/splitter/state.go @@ -61,13 +61,17 @@ func newState(config *Config, result *Result) (*state, error) { } if config.Debug { - state.logger.Printf("Splitting %s\n", state.originBranch) + state.logger.Printf("Splitting %s", state.originBranch) for _, v := range config.Prefixes { to := v.To if to == "" { to = "ROOT" } - state.logger.Printf(" From \"%s\" to \"%s\"\n", v.From, to) + state.logger.Printf(` From "%s" to "%s"`, v.From, to) + if (len(v.Excludes)) == 0 { + } else { + state.logger.Printf(` Excluding "%s"`, strings.Join(v.Excludes, `", "`)) + } } } @@ -79,7 +83,7 @@ func newState(config *Config, result *Result) (*state, error) { // simplePrefix contains the prefix when there is only one // with an empty value (target) - if len(config.Prefixes) == 1 && config.Prefixes[0].To == "" { + if len(config.Prefixes) == 1 && config.Prefixes[0].To == "" && len(config.Prefixes[0].Excludes) == 0 { state.simplePrefix = config.Prefixes[0].From } @@ -284,6 +288,14 @@ func (s *state) treeByPaths(tree *git.Tree) (*git.Tree, error) { continue } + if len(prefix.Excludes) > 0 { + prunedTree, err := s.pruneTree(splitTree, prefix.Excludes) + if err != nil { + return nil, err + } + splitTree = prunedTree + } + // adding the prefix if prefix.To != "" { prefixedTree, err = s.addPrefixToTree(splitTree, prefix.To) @@ -360,6 +372,53 @@ func (s *state) addPrefixToTree(tree *git.Tree, prefix string) (*git.Tree, error return prefixedTree, nil } +func (s *state) pruneTree(tree *git.Tree, excludes []string) (*git.Tree, error) { + var err error + treeBuilder, err := s.repo.TreeBuilder() + if err != nil { + return nil, err + } + defer treeBuilder.Free() + + err = tree.Walk(func(path string, entry *git.TreeEntry) error { + // always add files at the root directory + if entry.Type == git.ObjectBlob { + if err := treeBuilder.Insert(entry.Name, entry.Id, git.FilemodeBlob); err != nil { + return err + } + return nil + } + + if entry.Type != git.ObjectTree { + // should never happen + return fmt.Errorf("Unexpected entry %s/%s (type %s)", path, entry.Name, entry.Type) + } + + // exclude directory in excludes + for _, exclude := range excludes { + if entry.Name == exclude { + return git.TreeWalkSkip + } + } + + if err := treeBuilder.Insert(entry.Name, entry.Id, git.FilemodeTree); err != nil { + return err + } + return git.TreeWalkSkip + }) + + if err != nil { + return nil, err + } + + treeOid, err := treeBuilder.Write() + if err != nil { + return nil, err + } + + return s.repo.LookupTree(treeOid) +} + func (s *state) copyOrSkip(rev *git.Commit, tree *git.Tree, newParents []*git.Oid) (*git.Oid, bool, error) { var identical, nonIdentical *git.Oid var gotParents []*git.Oid From bd864e2ca6a8156840f7cc129e0274d1eaf401c4 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 8 Mar 2024 10:57:23 +0100 Subject: [PATCH 15/18] Sanitize prefix values --- main.go | 9 ++++----- splitter/config.go | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/main.go b/main.go index ea79764..a67b430 100644 --- a/main.go +++ b/main.go @@ -26,7 +26,7 @@ func (p *prefixesFlag) Set(value string) error { to := "" excludes := make([]string, 0) if len(parts) >= 2 { - to = parts[1] + to = strings.TrimRight(parts[1], "/") if len(parts) > 2 { for _, exclude := range parts[2:] { excludes = append(excludes, exclude) @@ -35,14 +35,13 @@ func (p *prefixesFlag) Set(value string) error { } // value must be unique - for _, prefix := range []*splitter.Prefix(*p) { - // FIXME: to should be normalized (xxx vs xxx/ for instance) + for _, prefix := range *p { if prefix.To == to { return fmt.Errorf("cannot have two prefix splits under the same directory: %s -> %s vs %s -> %s", prefix.From, prefix.To, from, to) } } - *p = append(*p, &splitter.Prefix{From: from, To: to, Excludes: excludes}) + *p = append(*p, splitter.NewPrefix(from, to, excludes)) return nil } @@ -79,7 +78,7 @@ func main() { config := &splitter.Config{ Path: path, Origin: origin, - Prefixes: []*splitter.Prefix(prefixes), + Prefixes: prefixes, Target: target, Commit: commit, Debug: debug, diff --git a/splitter/config.go b/splitter/config.go index 7a4a0ef..b5aefdb 100644 --- a/splitter/config.go +++ b/splitter/config.go @@ -3,6 +3,7 @@ package splitter import ( "fmt" "log" + "strings" "sync" git "github.com/libgit2/git2go/v34" @@ -16,6 +17,24 @@ type Prefix struct { Excludes []string } +// NewPrefix returns a new prefix, sanitizing the input +func NewPrefix(from, to string, excludes []string) *Prefix { + // remove the trailing slash (to avoid duplicating cache) + from = strings.TrimRight(from, "/") + to = strings.TrimRight(to, "/") + + // remove trailing slashes from excludes (as it does not mean anything) + for i, exclude := range excludes { + excludes[i] = strings.TrimRight(exclude, "/") + } + + return &Prefix{ + From: from, + To: to, + Excludes: excludes, + } +} + // Config represents a split configuration type Config struct { Prefixes []*Prefix From fd72641be1c6ead72a5205dbbb8ea1de706a098f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 8 Mar 2024 14:10:06 +0100 Subject: [PATCH 16/18] Rename originBranch to origin --- splitter/state.go | 14 +++++++------- splitter/utils.go | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/splitter/state.go b/splitter/state.go index 7cdc417..637798d 100644 --- a/splitter/state.go +++ b/splitter/state.go @@ -13,7 +13,7 @@ import ( type state struct { config *Config - originBranch string + origin string repoMu *sync.Mutex repo *git.Repository cache *cache @@ -52,16 +52,16 @@ func newState(config *Config, result *Result) (*state, error) { state.logger = log.New(os.Stderr, "", log.LstdFlags) } - if state.originBranch, err = normalizeOriginBranch(state.repo, config.Origin); err != nil { + if state.origin, err = normalizeOrigin(state.repo, config.Origin); err != nil { return nil, err } - if state.cache, err = newCache(state.originBranch, config); err != nil { + if state.cache, err = newCache(state.origin, config); err != nil { return nil, err } if config.Debug { - state.logger.Printf("Splitting %s", state.originBranch) + state.logger.Printf("Splitting %s", state.origin) for _, v := range config.Prefixes { to := v.To if to == "" { @@ -589,7 +589,7 @@ func (s *state) pushRevs(revWalk *git.RevWalk) error { if start != nil { s.result.moveHead(s.cache.get(start)) // FIXME: CHECK that this is an ancestor of the branch? - return revWalk.PushRange(fmt.Sprintf("%s..%s", start, s.originBranch)) + return revWalk.PushRange(fmt.Sprintf("%s..%s", start, s.origin)) } // find the latest split sha1 if any on origin @@ -600,10 +600,10 @@ func (s *state) pushRevs(revWalk *git.RevWalk) error { return err } s.result.moveHead(s.cache.get(start)) - return revWalk.PushRange(fmt.Sprintf("%s^..%s", start, s.originBranch)) + return revWalk.PushRange(fmt.Sprintf("%s^..%s", start, s.origin)) } - branch, err := s.repo.RevparseSingle(s.originBranch) + branch, err := s.repo.RevparseSingle(s.origin) if err != nil { return err } diff --git a/splitter/utils.go b/splitter/utils.go index 00328de..0e19bbf 100644 --- a/splitter/utils.go +++ b/splitter/utils.go @@ -56,7 +56,7 @@ func SplitMessage(message string) (string, string) { return subject, body } -func normalizeOriginBranch(repo *git.Repository, origin string) (string, error) { +func normalizeOrigin(repo *git.Repository, origin string) (string, error) { if origin == "" { origin = "HEAD" } From 0a0c9e0be9fed3cdfcf5616a254409dd6f0772a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Haracewiat?= Date: Thu, 28 Aug 2025 15:29:55 +0200 Subject: [PATCH 17/18] fix: preserve filemode in root directory --- splitter/state.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/splitter/state.go b/splitter/state.go index 637798d..a5da90a 100644 --- a/splitter/state.go +++ b/splitter/state.go @@ -383,7 +383,7 @@ func (s *state) pruneTree(tree *git.Tree, excludes []string) (*git.Tree, error) err = tree.Walk(func(path string, entry *git.TreeEntry) error { // always add files at the root directory if entry.Type == git.ObjectBlob { - if err := treeBuilder.Insert(entry.Name, entry.Id, git.FilemodeBlob); err != nil { + if err := treeBuilder.Insert(entry.Name, entry.Id, entry.Filemode); err != nil { return err } return nil From bc1bb28a9cf1089c4f95c442ea16bd084318d72b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Haracewiat?= Date: Thu, 28 Aug 2025 15:30:24 +0200 Subject: [PATCH 18/18] test: add test for filemode --- run-tests.sh | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/run-tests.sh b/run-tests.sh index 7155022..fc7570a 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -155,6 +155,37 @@ twigSplitTest() { cd ../ } +filemodeTest() { + rm -rf filemode + mkdir filemode + cd filemode + git init > /dev/null + + switchAsSammy "Sat, 24 Nov 1973 19:01:02 +0200" "Sat, 24 Nov 1973 19:11:22 +0200" + echo "a" > a + git add a + git commit -m"added a" > /dev/null + + switchAsFred "Sat, 24 Nov 1973 20:01:02 +0200" "Sat, 24 Nov 1973 20:11:22 +0200" + mkdir b/ + echo "b" > b/b + chmod +x b/b + git add b + git commit -m"added b" > /dev/null + + $LITE_PATH --prefix=b/::not-important:also-not-important --target refs/heads/split 2>/dev/null + FILEMODE=`git ls-tree -r --format='%(objectmode)' split b` + + if test "$FILEMODE" = "100755"; then + echo "Test #6 - OK" + else + echo "Test #6 - NOT OK" + exit 1 + fi + + cd ../ +} + LITE_PATH=`pwd`/splitsh-lite if [ ! -e $LITE_PATH ]; then echo "You first need to compile the splitsh-lite binary" @@ -169,3 +200,4 @@ cd splitter-lite-tests simpleTest mergeTest twigSplitTest +filemodeTest