forked from go-gitea/gitea
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <mathieu.guay-paquet@polymtl.ca>
- Loading branch information
Showing
6 changed files
with
898 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// Copyright 2023 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package util | ||
|
||
import ( | ||
"bytes" | ||
"io" | ||
"os" | ||
) | ||
|
||
// Decide if two files have the same contents or not. | ||
// chunkSize is the size of the blocks to scan by; pass 0 to get a sensible default. | ||
// *Follows* symlinks. | ||
// | ||
// May return an error if something else goes wrong; in this case, you should ignore the value of 'same'. | ||
// | ||
// derived from https://stackoverflow.com/a/30038571 | ||
// under CC-BY-SA-4.0 by several contributors | ||
func FileCmp(file1, file2 string, chunkSize int) (same bool, err error) { | ||
if chunkSize == 0 { | ||
chunkSize = 4 * 1024 | ||
} | ||
|
||
// shortcuts: check file metadata | ||
stat1, err := os.Stat(file1) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
stat2, err := os.Stat(file2) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
// are inputs are literally the same file? | ||
if os.SameFile(stat1, stat2) { | ||
return true, nil | ||
} | ||
|
||
// do inputs at least have the same size? | ||
if stat1.Size() != stat2.Size() { | ||
return false, nil | ||
} | ||
|
||
// long way: compare contents | ||
f1, err := os.Open(file1) | ||
if err != nil { | ||
return false, err | ||
} | ||
defer f1.Close() | ||
|
||
f2, err := os.Open(file2) | ||
if err != nil { | ||
return false, err | ||
} | ||
defer f2.Close() | ||
|
||
b1 := make([]byte, chunkSize) | ||
b2 := make([]byte, chunkSize) | ||
for { | ||
n1, err1 := io.ReadFull(f1, b1) | ||
n2, err2 := io.ReadFull(f2, b2) | ||
|
||
// https://pkg.go.dev/io#Reader | ||
// > Callers should always process the n > 0 bytes returned | ||
// > before considering the error err. Doing so correctly | ||
// > handles I/O errors that happen after reading some bytes | ||
// > and also both of the allowed EOF behaviors. | ||
|
||
if !bytes.Equal(b1[:n1], b2[:n2]) { | ||
return false, nil | ||
} | ||
|
||
if (err1 == io.EOF && err2 == io.EOF) || (err1 == io.ErrUnexpectedEOF && err2 == io.ErrUnexpectedEOF) { | ||
return true, nil | ||
} | ||
|
||
// some other error, like a dropped network connection or a bad transfer | ||
if err1 != nil { | ||
return false, err1 | ||
} | ||
if err2 != nil { | ||
return false, err2 | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.