Skip to content

Commit dba5d09

Browse files
kousumguaypaq
authored andcommitted
git-annex tests (#13)
Fixes #11 Tests: * `git annex init` * `git annex copy --from origin` * `git annex copy --to origin` over: * ssh for: * the owner * a collaborator * a read-only collaborator * a stranger in a * public repo * private repo And then confirms: * Deletion of the remote repo (to ensure lockdown isn't messing with us: https://git-annex.branchable.com/internals/lockdown/#comment-0cc5225dc5abe8eddeb843bfd2fdc382) ------ To support all this: * Add util.FileCmp() * Patch withKeyFile() so it can be nested in other copies of itself ------- Many thanks to Mathieu for giving style tips and catching several bugs, including a subtle one in util.filecmp() which neutered it. Co-authored-by: Mathieu Guay-Paquet <[email protected]>
1 parent 67ec292 commit dba5d09

File tree

6 files changed

+898
-1
lines changed

6 files changed

+898
-1
lines changed

.github/workflows/pull-db-tests.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ jobs:
4646
- name: Add hosts to /etc/hosts
4747
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 pgsql ldap minio" | sudo tee -a /etc/hosts'
4848
- run: make deps-backend
49+
- run: sudo apt update && sudo DEBIAN_FRONTEND=noninteractive apt install -y git-annex
4950
- run: make backend
5051
env:
5152
TAGS: bindata
@@ -69,6 +70,7 @@ jobs:
6970
go-version-file: go.mod
7071
check-latest: true
7172
- run: make deps-backend
73+
- run: sudo apt update && sudo DEBIAN_FRONTEND=noninteractive apt install -y git-annex
7274
- run: make backend
7375
env:
7476
TAGS: bindata gogit sqlite sqlite_unlock_notify
@@ -172,6 +174,7 @@ jobs:
172174
- name: Add hosts to /etc/hosts
173175
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mysql elasticsearch smtpimap" | sudo tee -a /etc/hosts'
174176
- run: make deps-backend
177+
- run: sudo apt update && sudo DEBIAN_FRONTEND=noninteractive apt install -y git-annex
175178
- run: make backend
176179
env:
177180
TAGS: bindata
@@ -205,6 +208,7 @@ jobs:
205208
- name: Add hosts to /etc/hosts
206209
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mssql" | sudo tee -a /etc/hosts'
207210
- run: make deps-backend
211+
- run: sudo apt update && sudo DEBIAN_FRONTEND=noninteractive apt install -y git-annex
208212
- run: make backend
209213
env:
210214
TAGS: bindata

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ self := $(location)
88
@tmpdir=`mktemp --tmpdir -d` ; \
99
echo Using temporary directory $$tmpdir for test repositories ; \
1010
USE_REPO_TEST_DIR= $(MAKE) -f $(self) --no-print-directory REPO_TEST_DIR=$$tmpdir/ $@ ; \
11-
STATUS=$$? ; rm -r "$$tmpdir" ; exit $$STATUS
11+
STATUS=$$? ; chmod -R +w "$$tmpdir" && rm -r "$$tmpdir" ; exit $$STATUS
1212

1313
else
1414

modules/util/filecmp.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package util
5+
6+
import (
7+
"bytes"
8+
"io"
9+
"os"
10+
)
11+
12+
// Decide if two files have the same contents or not.
13+
// chunkSize is the size of the blocks to scan by; pass 0 to get a sensible default.
14+
// *Follows* symlinks.
15+
//
16+
// May return an error if something else goes wrong; in this case, you should ignore the value of 'same'.
17+
//
18+
// derived from https://stackoverflow.com/a/30038571
19+
// under CC-BY-SA-4.0 by several contributors
20+
func FileCmp(file1, file2 string, chunkSize int) (same bool, err error) {
21+
if chunkSize == 0 {
22+
chunkSize = 4 * 1024
23+
}
24+
25+
// shortcuts: check file metadata
26+
stat1, err := os.Stat(file1)
27+
if err != nil {
28+
return false, err
29+
}
30+
31+
stat2, err := os.Stat(file2)
32+
if err != nil {
33+
return false, err
34+
}
35+
36+
// are inputs are literally the same file?
37+
if os.SameFile(stat1, stat2) {
38+
return true, nil
39+
}
40+
41+
// do inputs at least have the same size?
42+
if stat1.Size() != stat2.Size() {
43+
return false, nil
44+
}
45+
46+
// long way: compare contents
47+
f1, err := os.Open(file1)
48+
if err != nil {
49+
return false, err
50+
}
51+
defer f1.Close()
52+
53+
f2, err := os.Open(file2)
54+
if err != nil {
55+
return false, err
56+
}
57+
defer f2.Close()
58+
59+
b1 := make([]byte, chunkSize)
60+
b2 := make([]byte, chunkSize)
61+
for {
62+
n1, err1 := io.ReadFull(f1, b1)
63+
n2, err2 := io.ReadFull(f2, b2)
64+
65+
// https://pkg.go.dev/io#Reader
66+
// > Callers should always process the n > 0 bytes returned
67+
// > before considering the error err. Doing so correctly
68+
// > handles I/O errors that happen after reading some bytes
69+
// > and also both of the allowed EOF behaviors.
70+
71+
if !bytes.Equal(b1[:n1], b2[:n2]) {
72+
return false, nil
73+
}
74+
75+
if (err1 == io.EOF && err2 == io.EOF) || (err1 == io.ErrUnexpectedEOF && err2 == io.ErrUnexpectedEOF) {
76+
return true, nil
77+
}
78+
79+
// some other error, like a dropped network connection or a bad transfer
80+
if err1 != nil {
81+
return false, err1
82+
}
83+
if err2 != nil {
84+
return false, err2
85+
}
86+
}
87+
}

tests/integration/api_helper_for_declarative_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
api "code.gitea.io/gitea/modules/structs"
2222
"code.gitea.io/gitea/services/forms"
2323

24+
"github.com/google/uuid"
2425
"github.com/stretchr/testify/assert"
2526
)
2627

@@ -462,3 +463,27 @@ func doAPIAddRepoToOrganizationTeam(ctx APITestContext, teamID int64, orgName, r
462463
ctx.Session.MakeRequest(t, req, http.StatusNoContent)
463464
}
464465
}
466+
467+
// generate and activate an ssh key for the user attached to the APITestContext
468+
// TODO: pick a better name; golang doesn't do method overriding.
469+
func withCtxKeyFile(t *testing.T, ctx APITestContext, callback func()) {
470+
// we need to have write:public_key to do this step
471+
// the easiest way is to create a throwaway ctx that is identical but only has that permission
472+
ctxKeyWriter := ctx
473+
ctxKeyWriter.Token = getTokenForLoggedInUser(t, ctx.Session, auth.AccessTokenScopeWriteUser)
474+
475+
keyName := "One of " + ctx.Username + "'s keys: #" + uuid.New().String()
476+
withKeyFile(t, keyName, func(keyFile string) {
477+
var key api.PublicKey
478+
479+
doAPICreateUserKey(ctxKeyWriter, keyName, keyFile,
480+
func(t *testing.T, _key api.PublicKey) {
481+
// save the key ID so we can delete it at the end
482+
key = _key
483+
})(t)
484+
485+
defer doAPIDeleteUserKey(ctxKeyWriter, key.ID)(t)
486+
487+
callback()
488+
})
489+
}

0 commit comments

Comments
 (0)