diff options
| author | mo khan <mo@mokhan.ca> | 2026-01-30 17:18:31 -0700 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2026-01-30 17:18:31 -0700 |
| commit | e4ed0342932b0aa741ee78d9e4fe135eba6e9ca7 (patch) | |
| tree | f1e7f602cb86e78aedf04185b2c2e1428fc5b8f2 | |
| parent | 83be9ddcf82e8a90ea50a9d54c1ebfc3e22ace16 (diff) | |
initial commit
147 files changed, 44 insertions, 6193 deletions
diff --git a/.github/scripts/build.mjs b/.github/scripts/build.mjs deleted file mode 100755 index 251a036..0000000 --- a/.github/scripts/build.mjs +++ /dev/null @@ -1,33 +0,0 @@ -$.verbose = true - -const goos = [ - 'linux', - 'darwin', - 'windows', -] -const goarch = [ - 'amd64', - 'arm64', -] - -const name = (GOOS, GOARCH) => `gitmal_${GOOS}_${GOARCH}` + (GOOS === 'windows' ? '.exe' : '') - -const resp = await fetch('https://api.github.com/repos/antonmedv/gitmal/releases/latest') -const {tag_name: latest} = await resp.json() - -await $`go mod download` - -await Promise.all( - goos.flatMap(GOOS => - goarch.map(GOARCH => - $`GOOS=${GOOS} GOARCH=${GOARCH} go build -o ${name(GOOS, GOARCH)}`))) - -await Promise.all( - goos.flatMap(GOOS => - goarch.map(GOARCH => - $`gh release upload ${latest} ${name(GOOS, GOARCH)}`))) - -await Promise.all( - goos.flatMap(GOOS => - goarch.map(GOARCH => - $`rm ${name(GOOS, GOARCH)}`))) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml deleted file mode 100644 index 76f5c33..0000000 --- a/.github/workflows/release.yaml +++ /dev/null @@ -1,43 +0,0 @@ -name: release - -on: - release: - types: [ created ] - workflow_dispatch: - -jobs: - docker: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: antonmedv - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build test image - uses: docker/build-push-action@v5 - with: - context: . - file: ./Dockerfile - load: true - tags: antonmedv/gitmal:test - - - name: Smoke test - verify binary runs - run: | - docker run --rm antonmedv/gitmal:test --help - - - name: Build and push - uses: docker/build-push-action@v5 - with: - context: . - file: ./Dockerfile - push: true - platforms: linux/amd64,linux/arm64 - tags: antonmedv/gitmal:latest diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml deleted file mode 100644 index 8b20693..0000000 --- a/.github/workflows/test.yaml +++ /dev/null @@ -1,18 +0,0 @@ -name: test - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v3 - with: - go-version: 1.21 - - name: Test - run: go test ./... diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 6a189a1..0000000 --- a/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -FROM golang:latest as builder - -WORKDIR /go - -COPY go.mod go.sum ./ - -RUN go mod download - -COPY . . - -RUN CGO_ENABLED=0 go build -o gitmal . - - -FROM alpine - -RUN apk add --no-cache git - -COPY --from=builder /go/gitmal /bin/gitmal - -WORKDIR /data - -ENV COLORTERM=truecolor - -ENTRYPOINT ["/bin/gitmal"] diff --git a/LICENSE b/LICENSE deleted file mode 100644 index ae6cff9..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 Anton Medvedev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index 6e76737..0000000 --- a/README.md +++ /dev/null @@ -1,67 +0,0 @@ -<p align="center"><img src="img/gitmal-color-logo.webp" alt="Gitmal" width="330" height="330"></p> - -# Gitmal - -Gitmal is a static page generator for Git repositories. Gitmal generates static HTML pages with files, commits, -code highlighting, and markdown rendering. - -## Installation - -```sh -go install github.com/antonmedv/gitmal@latest -``` - -```sh -docker run --rm -v $(pwd):/repo antonmedv/gitmal /repo -``` - -Or download prebuilt binary from [releases](https://github.com/antonmedv/gitmal/releases). - -## Usage - -Run gitmal in the repository dir. Gitmal will generate pages in _./output_ directory. - -```sh -gitmal . -``` - -Run gitmal with `--help` flag, go get a list of available options. - -```sh -gitmal --help -``` - -## Screenshots - -<p align="center"> - <a href="img/gitmal-screenshot-code-highlighting.webp"><img src="img/gitmal-screenshot-code-highlighting.webp" alt="Gitmal Code Highlighting" width="400"></a> - <a href="img/gitmal-screenshot-file-tree.webp"><img src="img/gitmal-screenshot-file-tree.webp" alt="Gitmal File Tree" width="400"></a><br> - <a href="img/gitmal-screenshot-files.webp"><img src="img/gitmal-screenshot-files.webp" alt="Gitmal Files Page" width="400"></a> -</p> - -## Examples - -Here are a few examples of repos hosted on my website: - -- [git.medv.io/zx/](https://git.medv.io/zx/) โ github.com/google/zx -- [git.medv.io/zig/](https://git.medv.io/zig/) โ codeberg.org/ziglang/zig (light theme) -- [git.medv.io/my-badges/](https://git.medv.io/my-badges/) โ github.com/my-badges/my-badges - -Gitmal on kubernetes repository works as well. Generation on my MacBook Air M2 with `--minify` and `--gzip` flags -takes around 25 minutes, and the generated files weigh around 2 GB. - -## Themes - -Gitmal supports different code highlighting themes. You can customize the theme with `--theme` flag. - -```sh -gitmal --theme github-dark -``` - -## Documentation - -- [How to Self-Host a Git Repository?](./docs/how-to-self-host-a-git-repository.md) - -## License - -[MIT](LICENSE) diff --git a/RELEASE.md b/RELEASE.md deleted file mode 100644 index ea715eb..0000000 --- a/RELEASE.md +++ /dev/null @@ -1,7 +0,0 @@ -# Release - -1. Create a [release](https://github.com/antonmedv/gitmal/releases/new) on GitHub. -2. Run [build.mjs](.github/scripts/build.mjs) to build and upload binaries. - ```sh - npx zx .github/scripts/build.mjs - ``` @@ -15,10 +15,10 @@ import ( "github.com/alecthomas/chroma/v2/lexers" "github.com/alecthomas/chroma/v2/styles" - "github.com/antonmedv/gitmal/pkg/git" - "github.com/antonmedv/gitmal/pkg/links" - "github.com/antonmedv/gitmal/pkg/progress_bar" - "github.com/antonmedv/gitmal/pkg/templates" + "mokhan.ca/antonmedv/gitmal/pkg/git" + "mokhan.ca/antonmedv/gitmal/pkg/links" + "mokhan.ca/antonmedv/gitmal/pkg/progress_bar" + "mokhan.ca/antonmedv/gitmal/pkg/templates" ) func generateBlobs(files []git.Blob, params Params) error { diff --git a/branches.go b/branches.go index 7faf037..d574954 100644 --- a/branches.go +++ b/branches.go @@ -6,8 +6,8 @@ import ( "path/filepath" "sort" - "github.com/antonmedv/gitmal/pkg/git" - "github.com/antonmedv/gitmal/pkg/templates" + "mokhan.ca/antonmedv/gitmal/pkg/git" + "mokhan.ca/antonmedv/gitmal/pkg/templates" ) // generateBranches creates a branches.html page at the root of the output @@ -17,10 +17,10 @@ import ( "github.com/alecthomas/chroma/v2/lexers" "github.com/alecthomas/chroma/v2/styles" - "github.com/antonmedv/gitmal/pkg/git" - "github.com/antonmedv/gitmal/pkg/gitdiff" - "github.com/antonmedv/gitmal/pkg/progress_bar" - "github.com/antonmedv/gitmal/pkg/templates" + "mokhan.ca/antonmedv/gitmal/pkg/git" + "mokhan.ca/antonmedv/gitmal/pkg/gitdiff" + "mokhan.ca/antonmedv/gitmal/pkg/progress_bar" + "mokhan.ca/antonmedv/gitmal/pkg/templates" ) func generateCommits(commits map[string]git.Commit, params Params) error { diff --git a/commits_list.go b/commits_list.go index b09424e..14b3921 100644 --- a/commits_list.go +++ b/commits_list.go @@ -6,9 +6,9 @@ import ( "path/filepath" "slices" - "github.com/antonmedv/gitmal/pkg/git" - "github.com/antonmedv/gitmal/pkg/progress_bar" - "github.com/antonmedv/gitmal/pkg/templates" + "mokhan.ca/antonmedv/gitmal/pkg/git" + "mokhan.ca/antonmedv/gitmal/pkg/progress_bar" + "mokhan.ca/antonmedv/gitmal/pkg/templates" ) const commitsPerPage = 100 diff --git a/docs/how-to-self-host-a-git-repository.md b/docs/how-to-self-host-a-git-repository.md deleted file mode 100644 index 799dbe3..0000000 --- a/docs/how-to-self-host-a-git-repository.md +++ /dev/null @@ -1,67 +0,0 @@ -# How to Self-Host a Git Repository? - -**Goal**: self-host a Git repository on your server, allowing read-only clones and a web view. - -Create a _git_ user on the server where you want to host the repository. This step is optional, but I like to use a -dedicated user for repository management to keep the system secure and organized. - -Create a `~/public` directory, which will serve as the web root. Configure a web server to serve files from this -directory. - -## Bare repo - -Create a bare repository inside `~/public`. -A [bare repository](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols) -is a special type of Git repository that doesn't have a working directory. It's used for hosting and sharing code -without the need for a local working copy. - -```sh -git init --bare repo.git -``` - -Create a [post-update](https://git-scm.com/docs/git-receive-pack#_post_update_hook) hook with the following content: - -```sh -#!/bin/sh -exec git update-server-info -``` - -Make the hook executable: - -```sh -chmod +x hooks/post-update -``` - -## Gitmal hook - -Create a [postโreceive](https://git-scm.com/docs/git-receive-pack#_post_receive_hook) hook with the following content: - -```sh -#!/bin/sh -exec gitmal --output /home/git/public/repo/ -``` - -Make the hook executable: - -```sh -chmod +x hooks/post-receive -``` - -## Publish - -Push your local repository to the bare repository on the server using ssh protocol. - -```sh -git remote add origin git@example.com:public/repo.git -git push origin master -``` - -After pushing, git will run gitmal and generate files under `~/public/repo/` directory. - -- Private read-write clone URL: `git@example.com:public/repo.git` -- Public **read-only** clone URL: `http://example.com/repo.git` -- Gitmal static web view: `http://example.com/repo/` - -```sh -git clone https://example.com/repo.git -``` @@ -1,4 +1,4 @@ -module github.com/antonmedv/gitmal +module mokhan.ca/antonmedv/gitmal go 1.24.0 diff --git a/img/gitmal-color-logo.webp b/img/gitmal-color-logo.webp Binary files differdeleted file mode 100644 index f7320e1..0000000 --- a/img/gitmal-color-logo.webp +++ /dev/null diff --git a/img/gitmal-screenshot-code-highlighting.webp b/img/gitmal-screenshot-code-highlighting.webp Binary files differdeleted file mode 100644 index 7c8b94c..0000000 --- a/img/gitmal-screenshot-code-highlighting.webp +++ /dev/null diff --git a/img/gitmal-screenshot-file-tree.webp b/img/gitmal-screenshot-file-tree.webp Binary files differdeleted file mode 100644 index 032013c..0000000 --- a/img/gitmal-screenshot-file-tree.webp +++ /dev/null diff --git a/img/gitmal-screenshot-files.webp b/img/gitmal-screenshot-files.webp Binary files differdeleted file mode 100644 index 57d0c60..0000000 --- a/img/gitmal-screenshot-files.webp +++ /dev/null diff --git a/img/gitmal-smallest-logo.webp b/img/gitmal-smallest-logo.webp Binary files differdeleted file mode 100644 index da98152..0000000 --- a/img/gitmal-smallest-logo.webp +++ /dev/null @@ -6,9 +6,9 @@ import ( "sort" "strings" - "github.com/antonmedv/gitmal/pkg/git" - "github.com/antonmedv/gitmal/pkg/links" - "github.com/antonmedv/gitmal/pkg/templates" + "mokhan.ca/antonmedv/gitmal/pkg/git" + "mokhan.ca/antonmedv/gitmal/pkg/links" + "mokhan.ca/antonmedv/gitmal/pkg/templates" ) func generateIndex(files []git.Blob, params Params) error { @@ -11,10 +11,10 @@ import ( "strings" "sync" - "github.com/antonmedv/gitmal/pkg/git" - "github.com/antonmedv/gitmal/pkg/links" - "github.com/antonmedv/gitmal/pkg/progress_bar" - "github.com/antonmedv/gitmal/pkg/templates" + "mokhan.ca/antonmedv/gitmal/pkg/git" + "mokhan.ca/antonmedv/gitmal/pkg/links" + "mokhan.ca/antonmedv/gitmal/pkg/progress_bar" + "mokhan.ca/antonmedv/gitmal/pkg/templates" ) func generateLists(files []git.Blob, params Params) error { @@ -8,7 +8,7 @@ import ( "runtime/pprof" "strings" - "github.com/antonmedv/gitmal/pkg/git" + "mokhan.ca/antonmedv/gitmal/pkg/git" flag "github.com/spf13/pflag" ) diff --git a/markdown.go b/markdown.go index 1e5a30b..a2a48b5 100644 --- a/markdown.go +++ b/markdown.go @@ -9,7 +9,7 @@ import ( "github.com/yuin/goldmark/parser" gmhtml "github.com/yuin/goldmark/renderer/html" - "github.com/antonmedv/gitmal/pkg/templates" + "mokhan.ca/antonmedv/gitmal/pkg/templates" ) func createMarkdown(style string) goldmark.Markdown { diff --git a/pkg/git/git_test.go b/pkg/git/git_test.go deleted file mode 100644 index 7ec0eb1..0000000 --- a/pkg/git/git_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package git - -import ( - "testing" -) - -func TestParseRefNames_Empty(t *testing.T) { - got := parseRefNames("") - if len(got) != 0 { - t.Fatalf("expected empty slice, got %v", got) - } -} - -func TestParseRefNames_Mixed(t *testing.T) { - input := "HEAD -> main, tag: v1.0.0, origin/HEAD -> origin/main, origin/main, master" - got := parseRefNames(input) - if len(got) != 5 { - t.Fatalf("expected 5 entries, got %d (%v)", len(got), got) - } - - // 1: HEAD pointer - if got[0].Kind != RefKindHEAD || got[0].Name != "HEAD" || got[0].Target != "main" { - t.Errorf("unexpected HEAD entry: %+v", got[0]) - } - // 2: tag - if got[1].Kind != RefKindTag || got[1].Name != "v1.0.0" || got[1].Target != "" { - t.Errorf("unexpected Tag entry: %+v", got[1]) - } - // 3: remote HEAD pointer - if got[2].Kind != RefKindRemoteHEAD || got[2].Name != "origin/HEAD" || got[2].Target != "origin/main" { - t.Errorf("unexpected RemoteHEAD entry: %+v", got[2]) - } - // 4: remote branch - if got[3].Kind != RefKindRemote || got[3].Name != "origin/main" || got[3].Target != "" { - t.Errorf("unexpected Remote entry: %+v", got[3]) - } - // 5: local branch - if got[4].Kind != RefKindBranch || got[4].Name != "master" || got[4].Target != "" { - t.Errorf("unexpected Branch entry: %+v", got[4]) - } -} - -func TestParseRefNames_Singles(t *testing.T) { - cases := []struct { - in string - kind RefKind - name string - target string - }{ - {"tag: v2", RefKindTag, "v2", ""}, - {"main", RefKindBranch, "main", ""}, - {"origin/dev", RefKindRemote, "origin/dev", ""}, - {"origin/HEAD -> origin/main", RefKindRemoteHEAD, "origin/HEAD", "origin/main"}, - } - for _, c := range cases { - got := parseRefNames(c.in) - if len(got) != 1 { - t.Fatalf("%q: expected 1 entry, got %d (%v)", c.in, len(got), got) - } - if got[0].Kind != c.kind || got[0].Name != c.name || got[0].Target != c.target { - t.Errorf("%q: unexpected entry: %+v", c.in, got[0]) - } - } -} diff --git a/pkg/git/utils_test.go b/pkg/git/utils_test.go deleted file mode 100644 index 4dcebe8..0000000 --- a/pkg/git/utils_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package git_test - -import ( - "strings" - "testing" - - "github.com/antonmedv/gitmal/pkg/git" -) - -func TestParseFileMode(t *testing.T) { - tests := []struct { - mode string - expected string - }{ - {"100644", "rw-r--r--"}, - {"100755", "rwxr-xr-x"}, - {"100600", "rw-------"}, - {"100400", "r--------"}, - } - - for _, tt := range tests { - t.Run(tt.mode, func(t *testing.T) { - result, err := git.ParseFileMode(tt.mode) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if result != tt.expected { - t.Errorf("got %q, want %q", result, tt.expected) - } - }) - } -} - -func TestParseFileModeInvalid(t *testing.T) { - tests := []string{ - "", - "12", - "abc", - "10070x", - } - - for _, mode := range tests { - t.Run(mode, func(t *testing.T) { - result, err := git.ParseFileMode(mode) - if err == nil { - t.Error("expected error, got nil") - } - if result != "" { - t.Errorf("expected empty result, got %q", result) - } - if !strings.Contains(err.Error(), "invalid mode") && !strings.Contains(err.Error(), "strconv.Atoi") { - t.Errorf("unexpected error message: %v", err) - } - }) - } -} - -func TestRefToFileName(t *testing.T) { - tests := []struct { - in string - want string - }{ - {"main", "main"}, - {"master", "master"}, - {"release/v1.0", "release-v1.0"}, - {"feature/add-login", "feature-add-login"}, - {"bugfix\\windows\\path", "bugfix-windows-path"}, - {"1.0.0", "1.0.0"}, - {"1.x", "1.x"}, - } - - for _, tt := range tests { - t.Run(tt.in, func(t *testing.T) { - got := git.RefToFileName(tt.in) - if got != tt.want { - t.Fatalf("refToFileName(%q) = %q, want %q", tt.in, got, tt.want) - } - }) - } -} diff --git a/pkg/gitdiff/README.md b/pkg/gitdiff/README.md deleted file mode 100644 index 974bb70..0000000 --- a/pkg/gitdiff/README.md +++ /dev/null @@ -1 +0,0 @@ -This is a vendored copy of the [bluekeyes/go-gitdiff](https://github.com/bluekeyes/go-gitdiff) package. diff --git a/pkg/gitdiff/apply_test.go b/pkg/gitdiff/apply_test.go deleted file mode 100644 index 05915ba..0000000 --- a/pkg/gitdiff/apply_test.go +++ /dev/null @@ -1,235 +0,0 @@ -package gitdiff - -import ( - "bytes" - "errors" - "io" - "io/ioutil" - "path/filepath" - "testing" -) - -func TestApplyTextFragment(t *testing.T) { - tests := map[string]applyTest{ - "createFile": {Files: getApplyFiles("text_fragment_new")}, - "deleteFile": {Files: getApplyFiles("text_fragment_delete_all")}, - - "addStart": {Files: getApplyFiles("text_fragment_add_start")}, - "addMiddle": {Files: getApplyFiles("text_fragment_add_middle")}, - "addEnd": {Files: getApplyFiles("text_fragment_add_end")}, - "addEndNoEOL": {Files: getApplyFiles("text_fragment_add_end_noeol")}, - - "changeStart": {Files: getApplyFiles("text_fragment_change_start")}, - "changeMiddle": {Files: getApplyFiles("text_fragment_change_middle")}, - "changeEnd": {Files: getApplyFiles("text_fragment_change_end")}, - "changeEndEOL": {Files: getApplyFiles("text_fragment_change_end_eol")}, - "changeExact": {Files: getApplyFiles("text_fragment_change_exact")}, - "changeSingleNoEOL": {Files: getApplyFiles("text_fragment_change_single_noeol")}, - - "errorShortSrcBefore": { - Files: applyFiles{ - Src: "text_fragment_error.src", - Patch: "text_fragment_error_short_src_before.patch", - }, - Err: &Conflict{}, - }, - "errorShortSrc": { - Files: applyFiles{ - Src: "text_fragment_error.src", - Patch: "text_fragment_error_short_src.patch", - }, - Err: &Conflict{}, - }, - "errorContextConflict": { - Files: applyFiles{ - Src: "text_fragment_error.src", - Patch: "text_fragment_error_context_conflict.patch", - }, - Err: &Conflict{}, - }, - "errorDeleteConflict": { - Files: applyFiles{ - Src: "text_fragment_error.src", - Patch: "text_fragment_error_delete_conflict.patch", - }, - Err: &Conflict{}, - }, - "errorNewFile": { - Files: applyFiles{ - Src: "text_fragment_error.src", - Patch: "text_fragment_error_new_file.patch", - }, - Err: &Conflict{}, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - test.run(t, func(dst io.Writer, src io.ReaderAt, file *File) error { - if len(file.TextFragments) != 1 { - t.Fatalf("patch should contain exactly one fragment, but it has %d", len(file.TextFragments)) - } - applier := NewTextApplier(dst, src) - return applier.ApplyFragment(file.TextFragments[0]) - }) - }) - } -} - -func TestApplyBinaryFragment(t *testing.T) { - tests := map[string]applyTest{ - "literalCreate": {Files: getApplyFiles("bin_fragment_literal_create")}, - "literalModify": {Files: getApplyFiles("bin_fragment_literal_modify")}, - "deltaModify": {Files: getApplyFiles("bin_fragment_delta_modify")}, - "deltaModifyLarge": {Files: getApplyFiles("bin_fragment_delta_modify_large")}, - - "errorIncompleteAdd": { - Files: applyFiles{ - Src: "bin_fragment_delta_error.src", - Patch: "bin_fragment_delta_error_incomplete_add.patch", - }, - Err: "incomplete add", - }, - "errorIncompleteCopy": { - Files: applyFiles{ - Src: "bin_fragment_delta_error.src", - Patch: "bin_fragment_delta_error_incomplete_copy.patch", - }, - Err: "incomplete copy", - }, - "errorSrcSize": { - Files: applyFiles{ - Src: "bin_fragment_delta_error.src", - Patch: "bin_fragment_delta_error_src_size.patch", - }, - Err: &Conflict{}, - }, - "errorDstSize": { - Files: applyFiles{ - Src: "bin_fragment_delta_error.src", - Patch: "bin_fragment_delta_error_dst_size.patch", - }, - Err: "insufficient or extra data", - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - test.run(t, func(dst io.Writer, src io.ReaderAt, file *File) error { - applier := NewBinaryApplier(dst, src) - return applier.ApplyFragment(file.BinaryFragment) - }) - }) - } -} - -func TestApplyFile(t *testing.T) { - tests := map[string]applyTest{ - "textModify": { - Files: applyFiles{ - Src: "file_text.src", - Patch: "file_text_modify.patch", - Out: "file_text_modify.out", - }, - }, - "textDelete": { - Files: applyFiles{ - Src: "file_text.src", - Patch: "file_text_delete.patch", - Out: "file_text_delete.out", - }, - }, - "textErrorPartialDelete": { - Files: applyFiles{ - Src: "file_text.src", - Patch: "file_text_error_partial_delete.patch", - }, - Err: &Conflict{}, - }, - "binaryModify": { - Files: getApplyFiles("file_bin_modify"), - }, - "modeChange": { - Files: getApplyFiles("file_mode_change"), - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - test.run(t, func(dst io.Writer, src io.ReaderAt, file *File) error { - return Apply(dst, src, file) - }) - }) - } -} - -type applyTest struct { - Files applyFiles - Err interface{} -} - -func (at applyTest) run(t *testing.T, apply func(io.Writer, io.ReaderAt, *File) error) { - src, patch, out := at.Files.Load(t) - - files, _, err := Parse(bytes.NewReader(patch)) - if err != nil { - t.Fatalf("failed to parse patch file: %v", err) - } - if len(files) != 1 { - t.Fatalf("patch should contain exactly one file, but it has %d", len(files)) - } - - var dst bytes.Buffer - err = apply(&dst, bytes.NewReader(src), files[0]) - if at.Err != nil { - assertError(t, at.Err, err, "applying fragment") - return - } - if err != nil { - var aerr *ApplyError - if errors.As(err, &aerr) { - t.Fatalf("unexpected error applying: at %d: fragment %d at %d: %v", aerr.Line, aerr.Fragment, aerr.FragmentLine, err) - } else { - t.Fatalf("unexpected error applying: %v", err) - } - } - - if !bytes.Equal(out, dst.Bytes()) { - t.Errorf("incorrect result after apply\nexpected:\n%q\nactual:\n%q", out, dst.Bytes()) - } -} - -type applyFiles struct { - Src string - Patch string - Out string -} - -func getApplyFiles(name string) applyFiles { - return applyFiles{ - Src: name + ".src", - Patch: name + ".patch", - Out: name + ".out", - } -} - -func (f applyFiles) Load(t *testing.T) (src []byte, patch []byte, out []byte) { - load := func(name, kind string) []byte { - d, err := ioutil.ReadFile(filepath.Join("testdata", "apply", name)) - if err != nil { - t.Fatalf("failed to read %s file: %v", kind, err) - } - return d - } - - if f.Src != "" { - src = load(f.Src, "source") - } - if f.Patch != "" { - patch = load(f.Patch, "patch") - } - if f.Out != "" { - out = load(f.Out, "output") - } - return -} diff --git a/pkg/gitdiff/assert_test.go b/pkg/gitdiff/assert_test.go deleted file mode 100644 index 878f13c..0000000 --- a/pkg/gitdiff/assert_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package gitdiff - -import ( - "errors" - "strings" - "testing" -) - -func assertError(t *testing.T, expected interface{}, actual error, action string) { - if actual == nil { - t.Fatalf("expected error %s, but got nil", action) - } - - switch exp := expected.(type) { - case bool: - if !exp { - t.Fatalf("unexpected error %s: %v", action, actual) - } - case string: - if !strings.Contains(actual.Error(), exp) { - t.Fatalf("incorrect error %s: %q does not contain %q", action, actual.Error(), exp) - } - case error: - if !errors.Is(actual, exp) { - t.Fatalf("incorrect error %s: expected %T (%v), actual: %T (%v)", action, exp, exp, actual, actual) - } - default: - t.Fatalf("unsupported expected error type: %T", exp) - } -} diff --git a/pkg/gitdiff/base85_test.go b/pkg/gitdiff/base85_test.go deleted file mode 100644 index 672c471..0000000 --- a/pkg/gitdiff/base85_test.go +++ /dev/null @@ -1,118 +0,0 @@ -package gitdiff - -import ( - "bytes" - "testing" -) - -func TestBase85Decode(t *testing.T) { - tests := map[string]struct { - Input string - Output []byte - Err bool - }{ - "twoBytes": { - Input: "%KiWV", - Output: []byte{0xCA, 0xFE}, - }, - "fourBytes": { - Input: "007GV", - Output: []byte{0x0, 0x0, 0xCA, 0xFE}, - }, - "sixBytes": { - Input: "007GV%KiWV", - Output: []byte{0x0, 0x0, 0xCA, 0xFE, 0xCA, 0xFE}, - }, - "invalidCharacter": { - Input: "00'GV", - Err: true, - }, - "underpaddedSequence": { - Input: "007G", - Err: true, - }, - "dataUnderrun": { - Input: "007GV", - Output: make([]byte, 8), - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - dst := make([]byte, len(test.Output)) - err := base85Decode(dst, []byte(test.Input)) - if test.Err { - if err == nil { - t.Fatalf("expected error decoding base85 data, but got nil") - } - return - } - if err != nil { - t.Fatalf("unexpected error decoding base85 data: %v", err) - } - for i, b := range test.Output { - if dst[i] != b { - t.Errorf("incorrect byte at index %d: expected 0x%X, actual 0x%X", i, b, dst[i]) - } - } - }) - } -} - -func TestBase85Encode(t *testing.T) { - tests := map[string]struct { - Input []byte - Output string - }{ - "zeroBytes": { - Input: []byte{}, - Output: "", - }, - "twoBytes": { - Input: []byte{0xCA, 0xFE}, - Output: "%KiWV", - }, - "fourBytes": { - Input: []byte{0x0, 0x0, 0xCA, 0xFE}, - Output: "007GV", - }, - "sixBytes": { - Input: []byte{0x0, 0x0, 0xCA, 0xFE, 0xCA, 0xFE}, - Output: "007GV%KiWV", - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - dst := make([]byte, len(test.Output)) - base85Encode(dst, test.Input) - for i, b := range test.Output { - if dst[i] != byte(b) { - t.Errorf("incorrect character at index %d: expected '%c', actual '%c'", i, b, dst[i]) - } - } - }) - } -} - -func FuzzBase85Roundtrip(f *testing.F) { - f.Add([]byte{0x2b, 0x0d}) - f.Add([]byte{0xbc, 0xb4, 0x3f}) - f.Add([]byte{0xfa, 0x62, 0x05, 0x83, 0x24, 0x39, 0xd5, 0x25}) - f.Add([]byte{0x31, 0x59, 0x02, 0xa0, 0x61, 0x12, 0xd9, 0x43, 0xb8, 0x23, 0x1a, 0xb4, 0x02, 0xae, 0xfa, 0xcc, 0x22, 0xad, 0x41, 0xb9, 0xb8}) - - f.Fuzz(func(t *testing.T, in []byte) { - n := len(in) - dst := make([]byte, base85Len(n)) - out := make([]byte, n) - - base85Encode(dst, in) - if err := base85Decode(out, dst); err != nil { - t.Fatalf("unexpected error decoding base85 data: %v", err) - } - if !bytes.Equal(in, out) { - t.Errorf("decoded data differed from input data:\n input: %x\n output: %x\nencoding: %s\n", in, out, string(dst)) - } - }) -} diff --git a/pkg/gitdiff/binary_test.go b/pkg/gitdiff/binary_test.go deleted file mode 100644 index 64db243..0000000 --- a/pkg/gitdiff/binary_test.go +++ /dev/null @@ -1,324 +0,0 @@ -package gitdiff - -import ( - "encoding/binary" - "io" - "reflect" - "strings" - "testing" -) - -func TestParseBinaryMarker(t *testing.T) { - tests := map[string]struct { - Input string - IsBinary bool - HasData bool - Err bool - }{ - "binaryPatch": { - Input: "GIT binary patch\n", - IsBinary: true, - HasData: true, - }, - "binaryFileNoPatch": { - Input: "Binary files differ\n", - IsBinary: true, - HasData: false, - }, - "binaryFileNoPatchPaths": { - Input: "Binary files a/foo.bin and b/foo.bin differ\n", - IsBinary: true, - HasData: false, - }, - "fileNoPatch": { - Input: "Files differ\n", - IsBinary: true, - HasData: false, - }, - "textFile": { - Input: "@@ -10,14 +22,31 @@\n", - IsBinary: false, - HasData: false, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - isBinary, hasData, err := p.ParseBinaryMarker() - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing binary marker, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("unexpected error parsing binary marker: %v", err) - } - if test.IsBinary != isBinary { - t.Errorf("incorrect isBinary value: expected %t, actual %t", test.IsBinary, isBinary) - } - if test.HasData != hasData { - t.Errorf("incorrect hasData value: expected %t, actual %t", test.HasData, hasData) - } - }) - } -} - -func TestParseBinaryFragmentHeader(t *testing.T) { - tests := map[string]struct { - Input string - Output *BinaryFragment - Err bool - }{ - "delta": { - Input: "delta 1234\n", - Output: &BinaryFragment{ - Method: BinaryPatchDelta, - Size: 1234, - }, - }, - "literal": { - Input: "literal 1234\n", - Output: &BinaryFragment{ - Method: BinaryPatchLiteral, - Size: 1234, - }, - }, - "unknownMethod": { - Input: "compressed 1234\n", - Output: nil, - }, - "notAHeader": { - Input: "Binary files differ\n", - Output: nil, - }, - "invalidSize": { - Input: "delta 123abc\n", - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - frag, err := p.ParseBinaryFragmentHeader() - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing binary header, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("unexpected error parsing binary header: %v", err) - } - if !reflect.DeepEqual(test.Output, frag) { - t.Errorf("incorrect binary fragment\nexpected: %+v\n actual: %+v", test.Output, frag) - } - }) - } -} - -func TestParseBinaryChunk(t *testing.T) { - tests := map[string]struct { - Input string - Fragment BinaryFragment - Output []byte - Err string - }{ - "singleline": { - Input: "TcmZQzU|?i`U?w2V48*Je09XJG\n\n", - Fragment: BinaryFragment{ - Size: 20, - }, - Output: fib(5, binary.BigEndian), - }, - "multiline": { - Input: "zcmZQzU|?i`U?w2V48*KJ%mKu_Kr9NxN<eH5#F0Qe0f=7$l~*z_FeL$%-)3N7vt?l5\n" + - "zl3-vE2xVZ9%4J~CI>f->s?WfX|B-=Vs{#X~svra7Ekg#T|4s}nH;WnAZ)|1Y*`&cB\n" + - "s(sh?X(Uz6L^!Ou&aF*u`J!eibJifSrv0z>$Q%Hd(^HIJ<Y?5`S0gT5UE&u=k\n\n", - Fragment: BinaryFragment{ - Size: 160, - }, - Output: fib(40, binary.BigEndian), - }, - "shortLine": { - Input: "A00\n\n", - Err: "corrupt data line", - }, - "underpaddedLine": { - Input: "H00000000\n\n", - Err: "corrupt data line", - }, - "invalidLengthByte": { - Input: "!00000\n\n", - Err: "invalid length byte", - }, - "miscountedLine": { - Input: "H00000\n\n", - Err: "incorrect byte count", - }, - "invalidEncoding": { - Input: "TcmZQzU|?i'U?w2V48*Je09XJG\n", - Err: "invalid base85 byte", - }, - "noTrailingEmptyLine": { - Input: "TcmZQzU|?i`U?w2V48*Je09XJG\n", - Err: "unexpected EOF", - }, - "invalidCompression": { - Input: "F007GV%KiWV\n\n", - Err: "zlib", - }, - "incorrectSize": { - Input: "TcmZQzU|?i`U?w2V48*Je09XJG\n\n", - Fragment: BinaryFragment{ - Size: 16, - }, - Err: "16 byte fragment inflated to 20", - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - frag := test.Fragment - err := p.ParseBinaryChunk(&frag) - if test.Err != "" { - if err == nil || !strings.Contains(err.Error(), test.Err) { - t.Fatalf("expected error containing %q parsing binary chunk, but got %v", test.Err, err) - } - return - } - if err != nil { - t.Fatalf("unexpected error parsing binary chunk: %v", err) - } - if !reflect.DeepEqual(test.Output, frag.Data) { - t.Errorf("incorrect binary chunk\nexpected: %+v\n actual: %+v", test.Output, frag.Data) - } - }) - } -} - -func TestParseBinaryFragments(t *testing.T) { - tests := map[string]struct { - Input string - File File - - Binary bool - Fragment *BinaryFragment - ReverseFragment *BinaryFragment - Err bool - }{ - "dataWithReverse": { - Input: `GIT binary patch -literal 40 -gcmZQzU|?i` + "`" + `U?w2V48*KJ%mKu_Kr9NxN<eH500b)lkN^Mx - -literal 0 -HcmV?d00001 - -`, - Binary: true, - Fragment: &BinaryFragment{ - Method: BinaryPatchLiteral, - Size: 40, - Data: fib(10, binary.BigEndian), - }, - ReverseFragment: &BinaryFragment{ - Method: BinaryPatchLiteral, - Size: 0, - Data: []byte{}, - }, - }, - "dataWithoutReverse": { - Input: `GIT binary patch -literal 40 -gcmZQzU|?i` + "`" + `U?w2V48*KJ%mKu_Kr9NxN<eH500b)lkN^Mx - -`, - Binary: true, - Fragment: &BinaryFragment{ - Method: BinaryPatchLiteral, - Size: 40, - Data: fib(10, binary.BigEndian), - }, - }, - "noData": { - Input: "Binary files differ\n", - Binary: true, - }, - "text": { - Input: `@@ -1 +1 @@ --old line -+new line -`, - Binary: false, - }, - "missingData": { - Input: "GIT binary patch\n", - Err: true, - }, - "invalidData": { - Input: `GIT binary patch -literal 20 -TcmZQzU|?i'U?w2V48*Je09XJG - -`, - Err: true, - }, - "invalidReverseData": { - Input: `GIT binary patch -literal 20 -TcmZQzU|?i` + "`" + `U?w2V48*Je09XJG - -literal 0 -zcmV?d00001 - -`, - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - file := test.File - _, err := p.ParseBinaryFragments(&file) - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing binary fragments, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("unexpected error parsing binary fragments: %v", err) - } - if test.Binary != file.IsBinary { - t.Errorf("incorrect binary state: expected %t, actual %t", test.Binary, file.IsBinary) - } - if !reflect.DeepEqual(test.Fragment, file.BinaryFragment) { - t.Errorf("incorrect binary fragment\nexpected: %+v\n actual: %+v", test.Fragment, file.BinaryFragment) - } - if !reflect.DeepEqual(test.ReverseFragment, file.ReverseBinaryFragment) { - t.Errorf("incorrect reverse binary fragment\nexpected: %+v\n actual: %+v", test.ReverseFragment, file.ReverseBinaryFragment) - } - }) - } -} - -func fib(n int, ord binary.ByteOrder) []byte { - buf := make([]byte, 4*n) - for i := 0; i < len(buf); i += 4 { - if i < 8 { - ord.PutUint32(buf[i:], 1) - } else { - ord.PutUint32(buf[i:], ord.Uint32(buf[i-4:])+ord.Uint32(buf[i-8:])) - } - } - return buf -} diff --git a/pkg/gitdiff/file_header_test.go b/pkg/gitdiff/file_header_test.go deleted file mode 100644 index ef29833..0000000 --- a/pkg/gitdiff/file_header_test.go +++ /dev/null @@ -1,766 +0,0 @@ -package gitdiff - -import ( - "io" - "os" - "reflect" - "testing" -) - -func TestParseGitFileHeader(t *testing.T) { - tests := map[string]struct { - Input string - Output *File - Err bool - }{ - "fileContentChange": { - Input: `diff --git a/dir/file.txt b/dir/file.txt -index 1c23fcc..40a1b33 100644 ---- a/dir/file.txt -+++ b/dir/file.txt -@@ -2,3 +4,5 @@ -`, - Output: &File{ - OldName: "dir/file.txt", - NewName: "dir/file.txt", - OldMode: os.FileMode(0100644), - OldOIDPrefix: "1c23fcc", - NewOIDPrefix: "40a1b33", - }, - }, - "newFile": { - Input: `diff --git a/dir/file.txt b/dir/file.txt -new file mode 100644 -index 0000000..f5711e4 ---- /dev/null -+++ b/dir/file.txt -`, - Output: &File{ - NewName: "dir/file.txt", - NewMode: os.FileMode(0100644), - OldOIDPrefix: "0000000", - NewOIDPrefix: "f5711e4", - IsNew: true, - }, - }, - "newEmptyFile": { - Input: `diff --git a/empty.txt b/empty.txt -new file mode 100644 -index 0000000..e69de29 -`, - Output: &File{ - NewName: "empty.txt", - NewMode: os.FileMode(0100644), - OldOIDPrefix: "0000000", - NewOIDPrefix: "e69de29", - IsNew: true, - }, - }, - "deleteFile": { - Input: `diff --git a/dir/file.txt b/dir/file.txt -deleted file mode 100644 -index 44cc321..0000000 ---- a/dir/file.txt -+++ /dev/null -`, - Output: &File{ - OldName: "dir/file.txt", - OldMode: os.FileMode(0100644), - OldOIDPrefix: "44cc321", - NewOIDPrefix: "0000000", - IsDelete: true, - }, - }, - "changeMode": { - Input: `diff --git a/file.sh b/file.sh -old mode 100644 -new mode 100755 -`, - Output: &File{ - OldName: "file.sh", - NewName: "file.sh", - OldMode: os.FileMode(0100644), - NewMode: os.FileMode(0100755), - }, - }, - "rename": { - Input: `diff --git a/foo.txt b/bar.txt -similarity index 100% -rename from foo.txt -rename to bar.txt -`, - Output: &File{ - OldName: "foo.txt", - NewName: "bar.txt", - Score: 100, - IsRename: true, - }, - }, - "copy": { - Input: `diff --git a/file.txt b/copy.txt -similarity index 100% -copy from file.txt -copy to copy.txt -`, - Output: &File{ - OldName: "file.txt", - NewName: "copy.txt", - Score: 100, - IsCopy: true, - }, - }, - "missingDefaultFilename": { - Input: `diff --git a/foo.sh b/bar.sh -old mode 100644 -new mode 100755 -`, - Err: true, - }, - "missingNewFilename": { - Input: `diff --git a/file.txt b/file.txt -index 1c23fcc..40a1b33 100644 ---- a/file.txt -`, - Err: true, - }, - "missingOldFilename": { - Input: `diff --git a/file.txt b/file.txt -index 1c23fcc..40a1b33 100644 -+++ b/file.txt -`, - Err: true, - }, - "invalidHeaderLine": { - Input: `diff --git a/file.txt b/file.txt -index deadbeef ---- a/file.txt -+++ b/file.txt -`, - Err: true, - }, - "notGitHeader": { - Input: `--- file.txt -+++ file.txt -@@ -0,0 +1 @@ -`, - Output: nil, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - f, err := p.ParseGitFileHeader() - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing git file header, got %v", err) - } - return - } - if err != nil { - t.Fatalf("unexpected error parsing git file header: %v", err) - } - - if !reflect.DeepEqual(test.Output, f) { - t.Errorf("incorrect file\nexpected: %+v\n actual: %+v", test.Output, f) - } - }) - } -} - -func TestParseTraditionalFileHeader(t *testing.T) { - tests := map[string]struct { - Input string - Output *File - Err bool - }{ - "fileContentChange": { - Input: `--- dir/file_old.txt 2019-03-21 23:00:00.0 -0700 -+++ dir/file_new.txt 2019-03-21 23:30:00.0 -0700 -@@ -0,0 +1 @@ -`, - Output: &File{ - OldName: "dir/file_new.txt", - NewName: "dir/file_new.txt", - }, - }, - "newFile": { - Input: `--- /dev/null 1969-12-31 17:00:00.0 -0700 -+++ dir/file.txt 2019-03-21 23:30:00.0 -0700 -@@ -0,0 +1 @@ -`, - Output: &File{ - NewName: "dir/file.txt", - IsNew: true, - }, - }, - "newFileTimestamp": { - Input: `--- dir/file.txt 1969-12-31 17:00:00.0 -0700 -+++ dir/file.txt 2019-03-21 23:30:00.0 -0700 -@@ -0,0 +1 @@ -`, - Output: &File{ - NewName: "dir/file.txt", - IsNew: true, - }, - }, - "deleteFile": { - Input: `--- dir/file.txt 2019-03-21 23:30:00.0 -0700 -+++ /dev/null 1969-12-31 17:00:00.0 -0700 -@@ -0,0 +1 @@ -`, - Output: &File{ - OldName: "dir/file.txt", - IsDelete: true, - }, - }, - "deleteFileTimestamp": { - Input: `--- dir/file.txt 2019-03-21 23:30:00.0 -0700 -+++ dir/file.txt 1969-12-31 17:00:00.0 -0700 -@@ -0,0 +1 @@ -`, - Output: &File{ - OldName: "dir/file.txt", - IsDelete: true, - }, - }, - "useShortestPrefixName": { - Input: `--- dir/file.txt 2019-03-21 23:00:00.0 -0700 -+++ dir/file.txt~ 2019-03-21 23:30:00.0 -0700 -@@ -0,0 +1 @@ -`, - Output: &File{ - OldName: "dir/file.txt", - NewName: "dir/file.txt", - }, - }, - "notTraditionalHeader": { - Input: `diff --git a/dir/file.txt b/dir/file.txt ---- a/dir/file.txt -+++ b/dir/file.txt -`, - Output: nil, - }, - "noUnifiedFragment": { - Input: `--- dir/file_old.txt 2019-03-21 23:00:00.0 -0700 -+++ dir/file_new.txt 2019-03-21 23:30:00.0 -0700 -context line -+added line -`, - Output: nil, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - f, err := p.ParseTraditionalFileHeader() - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing traditional file header, got %v", err) - } - return - } - if err != nil { - t.Fatalf("unexpected error parsing traditional file header: %v", err) - } - - if !reflect.DeepEqual(test.Output, f) { - t.Errorf("incorrect file\nexpected: %+v\n actual: %+v", test.Output, f) - } - }) - } -} - -func TestCleanName(t *testing.T) { - tests := map[string]struct { - Input string - Drop int - Output string - }{ - "alreadyClean": { - Input: "a/b/c.txt", Output: "a/b/c.txt", - }, - "doubleSlashes": { - Input: "a//b/c.txt", Output: "a/b/c.txt", - }, - "tripleSlashes": { - Input: "a///b/c.txt", Output: "a/b/c.txt", - }, - "dropPrefix": { - Input: "a/b/c.txt", Drop: 2, Output: "c.txt", - }, - "removeDoublesBeforeDrop": { - Input: "a//b/c.txt", Drop: 1, Output: "b/c.txt", - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - output := cleanName(test.Input, test.Drop) - if output != test.Output { - t.Fatalf("incorrect output: expected %q, actual %q", test.Output, output) - } - }) - } -} - -func TestParseName(t *testing.T) { - tests := map[string]struct { - Input string - Term byte - Drop int - Output string - N int - Err bool - }{ - "singleUnquoted": { - Input: "dir/file.txt", Output: "dir/file.txt", N: 12, - }, - "singleQuoted": { - Input: `"dir/file.txt"`, Output: "dir/file.txt", N: 14, - }, - "quotedWithEscape": { - Input: `"dir/\"quotes\".txt"`, Output: `dir/"quotes".txt`, N: 20, - }, - "quotedWithSpaces": { - Input: `"dir/space file.txt"`, Output: "dir/space file.txt", N: 20, - }, - "tabTerminator": { - Input: "dir/space file.txt\tfile2.txt", Term: '\t', Output: "dir/space file.txt", N: 18, - }, - "dropPrefix": { - Input: "a/dir/file.txt", Drop: 1, Output: "dir/file.txt", N: 14, - }, - "unquotedWithSpaces": { - Input: "dir/with spaces.txt", Output: "dir/with spaces.txt", N: 19, - }, - "unquotedWithTrailingSpaces": { - Input: "dir/with spaces.space ", Output: "dir/with spaces.space ", N: 23, - }, - "devNull": { - Input: "/dev/null", Term: '\t', Drop: 1, Output: "/dev/null", N: 9, - }, - "newlineSeparates": { - Input: "dir/file.txt\n", Output: "dir/file.txt", N: 12, - }, - "emptyString": { - Input: "", Err: true, - }, - "emptyQuotedString": { - Input: `""`, Err: true, - }, - "unterminatedQuotes": { - Input: `"dir/file.txt`, Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - output, n, err := parseName(test.Input, test.Term, test.Drop) - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing name, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("unexpected error parsing name: %v", err) - } - - if output != test.Output { - t.Errorf("incorrect output: expected %q, actual: %q", test.Output, output) - } - if n != test.N { - t.Errorf("incorrect next position: expected %d, actual %d", test.N, n) - } - }) - } -} - -func TestParseGitHeaderData(t *testing.T) { - tests := map[string]struct { - InputFile *File - Line string - DefaultName string - - OutputFile *File - End bool - Err bool - }{ - "fragementEndsParsing": { - Line: "@@ -12,3 +12,2 @@\n", - End: true, - }, - "unknownEndsParsing": { - Line: "GIT binary file\n", - End: true, - }, - "oldFileName": { - Line: "--- a/dir/file.txt\n", - OutputFile: &File{ - OldName: "dir/file.txt", - }, - }, - "oldFileNameDevNull": { - InputFile: &File{ - IsNew: true, - }, - Line: "--- /dev/null\n", - OutputFile: &File{ - IsNew: true, - }, - }, - "oldFileNameInconsistent": { - InputFile: &File{ - OldName: "dir/foo.txt", - }, - Line: "--- a/dir/bar.txt\n", - Err: true, - }, - "oldFileNameExistingCreateMismatch": { - InputFile: &File{ - OldName: "dir/foo.txt", - IsNew: true, - }, - Line: "--- /dev/null\n", - Err: true, - }, - "oldFileNameParsedCreateMismatch": { - InputFile: &File{ - IsNew: true, - }, - Line: "--- a/dir/file.txt\n", - Err: true, - }, - "oldFileNameMissing": { - Line: "--- \n", - Err: true, - }, - "newFileName": { - Line: "+++ b/dir/file.txt\n", - OutputFile: &File{ - NewName: "dir/file.txt", - }, - }, - "newFileNameDevNull": { - InputFile: &File{ - IsDelete: true, - }, - Line: "+++ /dev/null\n", - OutputFile: &File{ - IsDelete: true, - }, - }, - "newFileNameInconsistent": { - InputFile: &File{ - NewName: "dir/foo.txt", - }, - Line: "+++ b/dir/bar.txt\n", - Err: true, - }, - "newFileNameExistingDeleteMismatch": { - InputFile: &File{ - NewName: "dir/foo.txt", - IsDelete: true, - }, - Line: "+++ /dev/null\n", - Err: true, - }, - "newFileNameParsedDeleteMismatch": { - InputFile: &File{ - IsDelete: true, - }, - Line: "+++ b/dir/file.txt\n", - Err: true, - }, - "newFileNameMissing": { - Line: "+++ \n", - Err: true, - }, - "oldMode": { - Line: "old mode 100644\n", - OutputFile: &File{ - OldMode: os.FileMode(0100644), - }, - }, - "oldModeWithTrailingSpace": { - Line: "old mode 100644\r\n", - OutputFile: &File{ - OldMode: os.FileMode(0100644), - }, - }, - "invalidOldMode": { - Line: "old mode rw\n", - Err: true, - }, - "newMode": { - Line: "new mode 100755\n", - OutputFile: &File{ - NewMode: os.FileMode(0100755), - }, - }, - "newModeWithTrailingSpace": { - Line: "new mode 100755\r\n", - OutputFile: &File{ - NewMode: os.FileMode(0100755), - }, - }, - "invalidNewMode": { - Line: "new mode rwx\n", - Err: true, - }, - "deletedFileMode": { - Line: "deleted file mode 100644\n", - DefaultName: "dir/file.txt", - OutputFile: &File{ - OldName: "dir/file.txt", - OldMode: os.FileMode(0100644), - IsDelete: true, - }, - }, - "newFileMode": { - Line: "new file mode 100755\n", - DefaultName: "dir/file.txt", - OutputFile: &File{ - NewName: "dir/file.txt", - NewMode: os.FileMode(0100755), - IsNew: true, - }, - }, - "newFileModeWithTrailingSpace": { - Line: "new file mode 100755\r\n", - DefaultName: "dir/file.txt", - OutputFile: &File{ - NewName: "dir/file.txt", - NewMode: os.FileMode(0100755), - IsNew: true, - }, - }, - "copyFrom": { - Line: "copy from dir/file.txt\n", - OutputFile: &File{ - OldName: "dir/file.txt", - IsCopy: true, - }, - }, - "copyTo": { - Line: "copy to dir/file.txt\n", - OutputFile: &File{ - NewName: "dir/file.txt", - IsCopy: true, - }, - }, - "renameFrom": { - Line: "rename from dir/file.txt\n", - OutputFile: &File{ - OldName: "dir/file.txt", - IsRename: true, - }, - }, - "renameTo": { - Line: "rename to dir/file.txt\n", - OutputFile: &File{ - NewName: "dir/file.txt", - IsRename: true, - }, - }, - "similarityIndex": { - Line: "similarity index 88%\n", - OutputFile: &File{ - Score: 88, - }, - }, - "similarityIndexTooBig": { - Line: "similarity index 9001%\n", - OutputFile: &File{ - Score: 0, - }, - }, - "similarityIndexInvalid": { - Line: "similarity index 12ab%\n", - Err: true, - }, - "indexFullSHA1AndMode": { - Line: "index 79c6d7f7b7e76c75b3d238f12fb1323f2333ba14..04fab916d8f938173cbb8b93469855f0e838f098 100644\n", - OutputFile: &File{ - OldOIDPrefix: "79c6d7f7b7e76c75b3d238f12fb1323f2333ba14", - NewOIDPrefix: "04fab916d8f938173cbb8b93469855f0e838f098", - OldMode: os.FileMode(0100644), - }, - }, - "indexFullSHA1NoMode": { - Line: "index 79c6d7f7b7e76c75b3d238f12fb1323f2333ba14..04fab916d8f938173cbb8b93469855f0e838f098\n", - OutputFile: &File{ - OldOIDPrefix: "79c6d7f7b7e76c75b3d238f12fb1323f2333ba14", - NewOIDPrefix: "04fab916d8f938173cbb8b93469855f0e838f098", - }, - }, - "indexAbbrevSHA1AndMode": { - Line: "index 79c6d7..04fab9 100644\n", - OutputFile: &File{ - OldOIDPrefix: "79c6d7", - NewOIDPrefix: "04fab9", - OldMode: os.FileMode(0100644), - }, - }, - "indexInvalid": { - Line: "index 79c6d7f7b7e76c75b3d238f12fb1323f2333ba14\n", - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - var f File - if test.InputFile != nil { - f = *test.InputFile - } - - end, err := parseGitHeaderData(&f, test.Line, test.DefaultName) - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing header data, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("unexpected error parsing header data: %v", err) - } - - if test.OutputFile != nil && !reflect.DeepEqual(test.OutputFile, &f) { - t.Errorf("incorrect output:\nexpected: %+v\nactual: %+v", test.OutputFile, &f) - } - if end != test.End { - t.Errorf("incorrect end state, expected %t, actual %t", test.End, end) - } - }) - } -} - -func TestParseGitHeaderName(t *testing.T) { - tests := map[string]struct { - Input string - Output string - Err bool - }{ - "twoMatchingNames": { - Input: "a/dir/file.txt b/dir/file.txt", - Output: "dir/file.txt", - }, - "twoDifferentNames": { - Input: "a/dir/foo.txt b/dir/bar.txt", - Output: "", - }, - "matchingNamesWithSpaces": { - Input: "a/dir/file with spaces.txt b/dir/file with spaces.txt", - Output: "dir/file with spaces.txt", - }, - "matchingNamesWithTrailingSpaces": { - Input: "a/dir/spaces b/dir/spaces ", - Output: "dir/spaces ", - }, - "matchingNamesQuoted": { - Input: `"a/dir/\"quotes\".txt" "b/dir/\"quotes\".txt"`, - Output: `dir/"quotes".txt`, - }, - "matchingNamesFirstQuoted": { - Input: `"a/dir/file.txt" b/dir/file.txt`, - Output: "dir/file.txt", - }, - "matchingNamesSecondQuoted": { - Input: `a/dir/file.txt "b/dir/file.txt"`, - Output: "dir/file.txt", - }, - "noSecondName": { - Input: "a/dir/foo.txt", - Output: "", - }, - "noSecondNameQuoted": { - Input: `"a/dir/foo.txt"`, - Output: "", - }, - "invalidName": { - Input: `"a/dir/file.txt b/dir/file.txt`, - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - output, err := parseGitHeaderName(test.Input) - if test.Err { - if err == nil { - t.Fatalf("expected error parsing header name, but got nil") - } - return - } - if err != nil { - t.Fatalf("unexpected error parsing header name: %v", err) - } - - if output != test.Output { - t.Errorf("incorrect output: expected %q, actual %q", test.Output, output) - } - }) - } -} - -func TestHasEpochTimestamp(t *testing.T) { - tests := map[string]struct { - Input string - Output bool - }{ - "utcTimestamp": { - Input: "+++ file.txt\t1970-01-01 00:00:00 +0000\n", - Output: true, - }, - "utcZoneWithColon": { - Input: "+++ file.txt\t1970-01-01 00:00:00 +00:00\n", - Output: true, - }, - "utcZoneWithMilliseconds": { - Input: "+++ file.txt\t1970-01-01 00:00:00.000000 +00:00\n", - Output: true, - }, - "westTimestamp": { - Input: "+++ file.txt\t1969-12-31 16:00:00 -0800\n", - Output: true, - }, - "eastTimestamp": { - Input: "+++ file.txt\t1970-01-01 04:00:00 +0400\n", - Output: true, - }, - "noTab": { - Input: "+++ file.txt 1970-01-01 00:00:00 +0000\n", - Output: false, - }, - "invalidFormat": { - Input: "+++ file.txt\t1970-01-01T00:00:00Z\n", - Output: false, - }, - "notEpoch": { - Input: "+++ file.txt\t2019-03-21 12:34:56.789 -0700\n", - Output: false, - }, - "notTimestamp": { - Input: "+++ file.txt\trandom text\n", - Output: false, - }, - "notTimestampShort": { - Input: "+++ file.txt\t0\n", - Output: false, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - output := hasEpochTimestamp(test.Input) - if output != test.Output { - t.Errorf("incorrect output: expected %t, actual %t", test.Output, output) - } - }) - } -} diff --git a/pkg/gitdiff/format_roundtrip_test.go b/pkg/gitdiff/format_roundtrip_test.go deleted file mode 100644 index a230e91..0000000 --- a/pkg/gitdiff/format_roundtrip_test.go +++ /dev/null @@ -1,157 +0,0 @@ -package gitdiff - -import ( - "bytes" - "fmt" - "os" - "path/filepath" - "slices" - "testing" -) - -func TestFormatRoundtrip(t *testing.T) { - patches := []struct { - File string - SkipTextCompare bool - }{ - {File: "copy.patch"}, - {File: "copy_modify.patch"}, - {File: "delete.patch"}, - {File: "mode.patch"}, - {File: "mode_modify.patch"}, - {File: "modify.patch"}, - {File: "new.patch"}, - {File: "new_empty.patch"}, - {File: "new_mode.patch"}, - {File: "rename.patch"}, - {File: "rename_modify.patch"}, - - // Due to differences between Go's 'encoding/zlib' package and the zlib - // C library, binary patches cannot be compared directly as the patch - // data is slightly different when re-encoded by Go. - {File: "binary_modify.patch", SkipTextCompare: true}, - {File: "binary_new.patch", SkipTextCompare: true}, - {File: "binary_modify_nodata.patch"}, - } - - for _, patch := range patches { - t.Run(patch.File, func(t *testing.T) { - b, err := os.ReadFile(filepath.Join("testdata", "string", patch.File)) - if err != nil { - t.Fatalf("failed to read patch: %v", err) - } - - original := assertParseSingleFile(t, b, "patch") - str := original.String() - - if !patch.SkipTextCompare { - if string(b) != str { - t.Errorf("incorrect patch text\nexpected: %q\n actual: %q\n", string(b), str) - } - } - - reparsed := assertParseSingleFile(t, []byte(str), "formatted patch") - assertFilesEqual(t, original, reparsed) - }) - } -} - -func assertParseSingleFile(t *testing.T, b []byte, kind string) *File { - files, _, err := Parse(bytes.NewReader(b)) - if err != nil { - t.Fatalf("failed to parse %s: %v", kind, err) - } - if len(files) != 1 { - t.Fatalf("expected %s to contain a single files, but found %d", kind, len(files)) - } - return files[0] -} - -func assertFilesEqual(t *testing.T, expected, actual *File) { - assertEqual(t, expected.OldName, actual.OldName, "OldName") - assertEqual(t, expected.NewName, actual.NewName, "NewName") - - assertEqual(t, expected.IsNew, actual.IsNew, "IsNew") - assertEqual(t, expected.IsDelete, actual.IsDelete, "IsDelete") - assertEqual(t, expected.IsCopy, actual.IsCopy, "IsCopy") - assertEqual(t, expected.IsRename, actual.IsRename, "IsRename") - - assertEqual(t, expected.OldMode, actual.OldMode, "OldMode") - assertEqual(t, expected.NewMode, actual.NewMode, "NewMode") - - assertEqual(t, expected.OldOIDPrefix, actual.OldOIDPrefix, "OldOIDPrefix") - assertEqual(t, expected.NewOIDPrefix, actual.NewOIDPrefix, "NewOIDPrefix") - assertEqual(t, expected.Score, actual.Score, "Score") - - if len(expected.TextFragments) == len(actual.TextFragments) { - for i := range expected.TextFragments { - prefix := fmt.Sprintf("TextFragments[%d].", i) - ef := expected.TextFragments[i] - af := actual.TextFragments[i] - - assertEqual(t, ef.Comment, af.Comment, prefix+"Comment") - - assertEqual(t, ef.OldPosition, af.OldPosition, prefix+"OldPosition") - assertEqual(t, ef.OldLines, af.OldLines, prefix+"OldLines") - - assertEqual(t, ef.NewPosition, af.NewPosition, prefix+"NewPosition") - assertEqual(t, ef.NewLines, af.NewLines, prefix+"NewLines") - - assertEqual(t, ef.LinesAdded, af.LinesAdded, prefix+"LinesAdded") - assertEqual(t, ef.LinesDeleted, af.LinesDeleted, prefix+"LinesDeleted") - - assertEqual(t, ef.LeadingContext, af.LeadingContext, prefix+"LeadingContext") - assertEqual(t, ef.TrailingContext, af.TrailingContext, prefix+"TrailingContext") - - if !slices.Equal(ef.Lines, af.Lines) { - t.Errorf("%sLines: expected %#v, actual %#v", prefix, ef.Lines, af.Lines) - } - } - } else { - t.Errorf("TextFragments: expected length %d, actual length %d", len(expected.TextFragments), len(actual.TextFragments)) - } - - assertEqual(t, expected.IsBinary, actual.IsBinary, "IsBinary") - - if expected.BinaryFragment != nil { - if actual.BinaryFragment == nil { - t.Errorf("BinaryFragment: expected non-nil, actual is nil") - } else { - ef := expected.BinaryFragment - af := expected.BinaryFragment - - assertEqual(t, ef.Method, af.Method, "BinaryFragment.Method") - assertEqual(t, ef.Size, af.Size, "BinaryFragment.Size") - - if !slices.Equal(ef.Data, af.Data) { - t.Errorf("BinaryFragment.Data: expected %#v, actual %#v", ef.Data, af.Data) - } - } - } else if actual.BinaryFragment != nil { - t.Errorf("BinaryFragment: expected nil, actual is non-nil") - } - - if expected.ReverseBinaryFragment != nil { - if actual.ReverseBinaryFragment == nil { - t.Errorf("ReverseBinaryFragment: expected non-nil, actual is nil") - } else { - ef := expected.ReverseBinaryFragment - af := expected.ReverseBinaryFragment - - assertEqual(t, ef.Method, af.Method, "ReverseBinaryFragment.Method") - assertEqual(t, ef.Size, af.Size, "ReverseBinaryFragment.Size") - - if !slices.Equal(ef.Data, af.Data) { - t.Errorf("ReverseBinaryFragment.Data: expected %#v, actual %#v", ef.Data, af.Data) - } - } - } else if actual.ReverseBinaryFragment != nil { - t.Errorf("ReverseBinaryFragment: expected nil, actual is non-nil") - } -} - -func assertEqual[T comparable](t *testing.T, expected, actual T, name string) { - if expected != actual { - t.Errorf("%s: expected %#v, actual %#v", name, expected, actual) - } -} diff --git a/pkg/gitdiff/format_test.go b/pkg/gitdiff/format_test.go deleted file mode 100644 index 3325296..0000000 --- a/pkg/gitdiff/format_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package gitdiff - -import ( - "strings" - "testing" -) - -func TestFormatter_WriteQuotedName(t *testing.T) { - tests := []struct { - Input string - Expected string - }{ - {"noquotes.txt", `noquotes.txt`}, - {"no quotes.txt", `no quotes.txt`}, - {"new\nline", `"new\nline"`}, - {"escape\x1B null\x00", `"escape\033 null\000"`}, - {"snowman \u2603 snowman", `"snowman \342\230\203 snowman"`}, - {"\"already quoted\"", `"\"already quoted\""`}, - } - - for _, test := range tests { - var b strings.Builder - newFormatter(&b).WriteQuotedName(test.Input) - if b.String() != test.Expected { - t.Errorf("expected %q, got %q", test.Expected, b.String()) - } - } -} diff --git a/pkg/gitdiff/gitdiff_test.go b/pkg/gitdiff/gitdiff_test.go deleted file mode 100644 index 4f63d51..0000000 --- a/pkg/gitdiff/gitdiff_test.go +++ /dev/null @@ -1,161 +0,0 @@ -package gitdiff - -import ( - "strings" - "testing" -) - -func TestTextFragmentValidate(t *testing.T) { - tests := map[string]struct { - Fragment TextFragment - Err string - }{ - "oldLines": { - Fragment: TextFragment{ - OldPosition: 1, - OldLines: 3, - NewPosition: 1, - NewLines: 2, - LeadingContext: 1, - TrailingContext: 0, - LinesAdded: 1, - LinesDeleted: 1, - Lines: []Line{ - {Op: OpContext, Line: "line 1\n"}, - {Op: OpDelete, Line: "old line 2\n"}, - {Op: OpAdd, Line: "new line 2\n"}, - }, - }, - Err: "2 old lines", - }, - "newLines": { - Fragment: TextFragment{ - OldPosition: 1, - OldLines: 2, - NewPosition: 1, - NewLines: 3, - LeadingContext: 1, - TrailingContext: 0, - LinesAdded: 1, - LinesDeleted: 1, - Lines: []Line{ - {Op: OpContext, Line: "line 1\n"}, - {Op: OpDelete, Line: "old line 2\n"}, - {Op: OpAdd, Line: "new line 2\n"}, - }, - }, - Err: "2 new lines", - }, - "leadingContext": { - Fragment: TextFragment{ - OldPosition: 1, - OldLines: 2, - NewPosition: 1, - NewLines: 2, - LeadingContext: 0, - TrailingContext: 0, - LinesAdded: 1, - LinesDeleted: 1, - Lines: []Line{ - {Op: OpContext, Line: "line 1\n"}, - {Op: OpDelete, Line: "old line 2\n"}, - {Op: OpAdd, Line: "new line 2\n"}, - }, - }, - Err: "1 leading context lines", - }, - "trailingContext": { - Fragment: TextFragment{ - OldPosition: 1, - OldLines: 4, - NewPosition: 1, - NewLines: 3, - LeadingContext: 1, - TrailingContext: 1, - LinesAdded: 1, - LinesDeleted: 2, - Lines: []Line{ - {Op: OpContext, Line: "line 1\n"}, - {Op: OpDelete, Line: "old line 2\n"}, - {Op: OpAdd, Line: "new line 2\n"}, - {Op: OpContext, Line: "line 3\n"}, - {Op: OpDelete, Line: "old line 4\n"}, - }, - }, - Err: "0 trailing context lines", - }, - "linesAdded": { - Fragment: TextFragment{ - OldPosition: 1, - OldLines: 4, - NewPosition: 1, - NewLines: 3, - LeadingContext: 1, - TrailingContext: 0, - LinesAdded: 2, - LinesDeleted: 2, - Lines: []Line{ - {Op: OpContext, Line: "line 1\n"}, - {Op: OpDelete, Line: "old line 2\n"}, - {Op: OpAdd, Line: "new line 2\n"}, - {Op: OpContext, Line: "line 3\n"}, - {Op: OpDelete, Line: "old line 4\n"}, - }, - }, - Err: "1 added lines", - }, - "linesDeleted": { - Fragment: TextFragment{ - OldPosition: 1, - OldLines: 4, - NewPosition: 1, - NewLines: 3, - LeadingContext: 1, - TrailingContext: 0, - LinesAdded: 1, - LinesDeleted: 1, - Lines: []Line{ - {Op: OpContext, Line: "line 1\n"}, - {Op: OpDelete, Line: "old line 2\n"}, - {Op: OpAdd, Line: "new line 2\n"}, - {Op: OpContext, Line: "line 3\n"}, - {Op: OpDelete, Line: "old line 4\n"}, - }, - }, - Err: "2 deleted lines", - }, - "fileCreation": { - Fragment: TextFragment{ - OldPosition: 0, - OldLines: 2, - NewPosition: 1, - NewLines: 1, - LeadingContext: 0, - TrailingContext: 0, - LinesAdded: 1, - LinesDeleted: 2, - Lines: []Line{ - {Op: OpDelete, Line: "old line 1\n"}, - {Op: OpDelete, Line: "old line 2\n"}, - {Op: OpAdd, Line: "new line\n"}, - }, - }, - Err: "creation fragment", - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - err := test.Fragment.Validate() - if test.Err == "" && err != nil { - t.Fatalf("unexpected validation error: %v", err) - } - if test.Err != "" && err == nil { - t.Fatal("expected validation error, but got nil") - } - if !strings.Contains(err.Error(), test.Err) { - t.Fatalf("incorrect validation error: %q is not in %q", test.Err, err.Error()) - } - }) - } -} diff --git a/pkg/gitdiff/io_test.go b/pkg/gitdiff/io_test.go deleted file mode 100644 index bd242a7..0000000 --- a/pkg/gitdiff/io_test.go +++ /dev/null @@ -1,254 +0,0 @@ -package gitdiff - -import ( - "bytes" - "fmt" - "io" - "math/rand" - "testing" -) - -func TestLineReaderAt(t *testing.T) { - const lineTemplate = "generated test line %d\n" - - tests := map[string]struct { - InputLines int - Offset int64 - Count int - Err bool - EOF bool - EOFCount int - }{ - "readLines": { - InputLines: 32, - Offset: 0, - Count: 4, - }, - "readLinesOffset": { - InputLines: 32, - Offset: 8, - Count: 4, - }, - "readLinesLargeOffset": { - InputLines: 8192, - Offset: 4096, - Count: 64, - }, - "readSingleLine": { - InputLines: 4, - Offset: 2, - Count: 1, - }, - "readZeroLines": { - InputLines: 4, - Offset: 2, - Count: 0, - }, - "readAllLines": { - InputLines: 64, - Offset: 0, - Count: 64, - }, - "readThroughEOF": { - InputLines: 16, - Offset: 12, - Count: 8, - EOF: true, - EOFCount: 4, - }, - "emptyInput": { - InputLines: 0, - Offset: 0, - Count: 2, - EOF: true, - EOFCount: 0, - }, - "offsetAfterEOF": { - InputLines: 8, - Offset: 10, - Count: 2, - EOF: true, - EOFCount: 0, - }, - "offsetNegative": { - InputLines: 8, - Offset: -1, - Count: 2, - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - var input bytes.Buffer - for i := 0; i < test.InputLines; i++ { - fmt.Fprintf(&input, lineTemplate, i) - } - - output := make([][]byte, test.Count) - for i := 0; i < test.Count; i++ { - output[i] = []byte(fmt.Sprintf(lineTemplate, test.Offset+int64(i))) - } - - r := &lineReaderAt{r: bytes.NewReader(input.Bytes())} - lines := make([][]byte, test.Count) - - n, err := r.ReadLinesAt(lines, test.Offset) - if test.Err { - if err == nil { - t.Fatal("expected error reading lines, but got nil") - } - return - } - if err != nil && (!test.EOF || err != io.EOF) { - t.Fatalf("unexpected error reading lines: %v", err) - } - - count := test.Count - if test.EOF { - count = test.EOFCount - } - - if n != count { - t.Fatalf("incorrect number of lines read: expected %d, actual %d", count, n) - } - for i := 0; i < n; i++ { - if !bytes.Equal(output[i], lines[i]) { - t.Errorf("incorrect content in line %d:\nexpected: %q\nactual: %q", i, output[i], lines[i]) - } - } - }) - } - - newlineTests := map[string]struct { - InputSize int - }{ - "readLinesNoFinalNewline": { - InputSize: indexBufferSize + indexBufferSize/2, - }, - "readLinesNoFinalNewlineBufferMultiple": { - InputSize: 4 * indexBufferSize, - }, - } - - for name, test := range newlineTests { - t.Run(name, func(t *testing.T) { - input := bytes.Repeat([]byte("0"), test.InputSize) - - var output [][]byte - for i := 0; i < len(input); i++ { - last := i - i += rand.Intn(80) - if i < len(input)-1 { // last character of input must not be a newline - input[i] = '\n' - output = append(output, input[last:i+1]) - } else { - output = append(output, input[last:]) - } - } - - r := &lineReaderAt{r: bytes.NewReader(input)} - lines := make([][]byte, len(output)) - - n, err := r.ReadLinesAt(lines, 0) - if err != nil { - t.Fatalf("unexpected error reading reading lines: %v", err) - } - - if n != len(output) { - t.Fatalf("incorrect number of lines read: expected %d, actual %d", len(output), n) - } - - for i, line := range lines { - if !bytes.Equal(output[i], line) { - t.Errorf("incorrect content in line %d:\nexpected: %q\nactual: %q", i, output[i], line) - } - } - }) - } -} - -func TestCopyFrom(t *testing.T) { - tests := map[string]struct { - Bytes int64 - Offset int64 - }{ - "copyAll": { - Bytes: byteBufferSize / 2, - }, - "copyPartial": { - Bytes: byteBufferSize / 2, - Offset: byteBufferSize / 4, - }, - "copyLarge": { - Bytes: 8 * byteBufferSize, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - data := make([]byte, test.Bytes) - rand.Read(data) - - var dst bytes.Buffer - n, err := copyFrom(&dst, bytes.NewReader(data), test.Offset) - if err != nil { - t.Fatalf("unexpected error copying data: %v", err) - } - if n != test.Bytes-test.Offset { - t.Fatalf("incorrect number of bytes copied: expected %d, actual %d", test.Bytes-test.Offset, n) - } - - expected := data[test.Offset:] - if !bytes.Equal(expected, dst.Bytes()) { - t.Fatalf("incorrect data copied:\nexpected: %v\nactual: %v", expected, dst.Bytes()) - } - }) - } -} - -func TestCopyLinesFrom(t *testing.T) { - tests := map[string]struct { - Lines int64 - Offset int64 - }{ - "copyAll": { - Lines: lineBufferSize / 2, - }, - "copyPartial": { - Lines: lineBufferSize / 2, - Offset: lineBufferSize / 4, - }, - "copyLarge": { - Lines: 8 * lineBufferSize, - }, - } - - const lineLength = 128 - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - data := make([]byte, test.Lines*lineLength) - for i := range data { - data[i] = byte(32 + rand.Intn(95)) // ascii letters, numbers, symbols - if i%lineLength == lineLength-1 { - data[i] = '\n' - } - } - - var dst bytes.Buffer - n, err := copyLinesFrom(&dst, &lineReaderAt{r: bytes.NewReader(data)}, test.Offset) - if err != nil { - t.Fatalf("unexpected error copying data: %v", err) - } - if n != test.Lines-test.Offset { - t.Fatalf("incorrect number of lines copied: expected %d, actual %d", test.Lines-test.Offset, n) - } - - expected := data[test.Offset*lineLength:] - if !bytes.Equal(expected, dst.Bytes()) { - t.Fatalf("incorrect data copied:\nexpected: %v\nactual: %v", expected, dst.Bytes()) - } - }) - } -} diff --git a/pkg/gitdiff/parser_test.go b/pkg/gitdiff/parser_test.go deleted file mode 100644 index 15a5d67..0000000 --- a/pkg/gitdiff/parser_test.go +++ /dev/null @@ -1,511 +0,0 @@ -package gitdiff - -import ( - "bytes" - "encoding/binary" - "encoding/json" - "io" - "os" - "reflect" - "testing" -) - -func TestLineOperations(t *testing.T) { - const content = "the first line\nthe second line\nthe third line\n" - - t.Run("read", func(t *testing.T) { - p := newTestParser(content, false) - - for i, expected := range []string{ - "the first line\n", - "the second line\n", - "the third line\n", - } { - if err := p.Next(); err != nil { - t.Fatalf("error advancing parser after line %d: %v", i, err) - } - if p.lineno != int64(i+1) { - t.Fatalf("incorrect line number: expected %d, actual: %d", i+1, p.lineno) - } - - line := p.Line(0) - if line != expected { - t.Fatalf("incorrect line %d: expected %q, was %q", i+1, expected, line) - } - } - - // reading after the last line should return EOF - if err := p.Next(); err != io.EOF { - t.Fatalf("expected EOF after end, but got: %v", err) - } - if p.lineno != 4 { - t.Fatalf("incorrect line number: expected %d, actual: %d", 4, p.lineno) - } - - // reading again returns EOF again and does not advance the line - if err := p.Next(); err != io.EOF { - t.Fatalf("expected EOF after end, but got: %v", err) - } - if p.lineno != 4 { - t.Fatalf("incorrect line number: expected %d, actual: %d", 4, p.lineno) - } - }) - - t.Run("peek", func(t *testing.T) { - p := newTestParser(content, false) - if err := p.Next(); err != nil { - t.Fatalf("error advancing parser: %v", err) - } - - line := p.Line(1) - if line != "the second line\n" { - t.Fatalf("incorrect peek line: %s", line) - } - - if err := p.Next(); err != nil { - t.Fatalf("error advancing parser after peek: %v", err) - } - - line = p.Line(0) - if line != "the second line\n" { - t.Fatalf("incorrect read line: %s", line) - } - }) - - t.Run("emptyInput", func(t *testing.T) { - p := newTestParser("", false) - if err := p.Next(); err != io.EOF { - t.Fatalf("expected EOF on first Next(), but got: %v", err) - } - }) -} - -func TestParserInvariant_Advancement(t *testing.T) { - tests := map[string]struct { - Input string - Parse func(p *parser) error - EndLine string - }{ - "ParseGitFileHeader": { - Input: `diff --git a/dir/file.txt b/dir/file.txt -index 9540595..30e6333 100644 ---- a/dir/file.txt -+++ b/dir/file.txt -@@ -1,2 +1,3 @@ -context line -`, - Parse: func(p *parser) error { - _, err := p.ParseGitFileHeader() - return err - }, - EndLine: "@@ -1,2 +1,3 @@\n", - }, - "ParseTraditionalFileHeader": { - Input: `--- dir/file.txt -+++ dir/file.txt -@@ -1,2 +1,3 @@ -context line -`, - Parse: func(p *parser) error { - _, err := p.ParseTraditionalFileHeader() - return err - }, - EndLine: "@@ -1,2 +1,3 @@\n", - }, - "ParseTextFragmentHeader": { - Input: `@@ -1,2 +1,3 @@ -context line -`, - Parse: func(p *parser) error { - _, err := p.ParseTextFragmentHeader() - return err - }, - EndLine: "context line\n", - }, - "ParseTextChunk": { - Input: ` context line --old line -+new line - context line -@@ -1 +1 @@ -`, - Parse: func(p *parser) error { - return p.ParseTextChunk(&TextFragment{OldLines: 3, NewLines: 3}) - }, - EndLine: "@@ -1 +1 @@\n", - }, - "ParseTextFragments": { - Input: `@@ -1,2 +1,2 @@ - context line --old line -+new line -@@ -1,2 +1,2 @@ --old line -+new line - context line -diff --git a/file.txt b/file.txt -`, - Parse: func(p *parser) error { - _, err := p.ParseTextFragments(&File{}) - return err - }, - EndLine: "diff --git a/file.txt b/file.txt\n", - }, - "ParseNextFileHeader": { - Input: `not a header -diff --git a/file.txt b/file.txt ---- a/file.txt -+++ b/file.txt -@@ -1,2 +1,2 @@ -`, - Parse: func(p *parser) error { - _, _, err := p.ParseNextFileHeader() - return err - }, - EndLine: "@@ -1,2 +1,2 @@\n", - }, - "ParseBinaryMarker": { - Input: `Binary files differ -diff --git a/file.txt b/file.txt -`, - Parse: func(p *parser) error { - _, _, err := p.ParseBinaryMarker() - return err - }, - EndLine: "diff --git a/file.txt b/file.txt\n", - }, - "ParseBinaryFragmentHeader": { - Input: `literal 0 -HcmV?d00001 -`, - Parse: func(p *parser) error { - _, err := p.ParseBinaryFragmentHeader() - return err - }, - EndLine: "HcmV?d00001\n", - }, - "ParseBinaryChunk": { - Input: "TcmZQzU|?i`" + `U?w2V48*Je09XJG - -literal 0 -`, - Parse: func(p *parser) error { - return p.ParseBinaryChunk(&BinaryFragment{Size: 20}) - }, - EndLine: "literal 0\n", - }, - "ParseBinaryFragments": { - Input: `GIT binary patch -literal 40 -gcmZQzU|?i` + "`" + `U?w2V48*KJ%mKu_Kr9NxN<eH500b)lkN^Mx - -literal 0 -HcmV?d00001 - -diff --git a/file.txt b/file.txt -`, - Parse: func(p *parser) error { - _, err := p.ParseBinaryFragments(&File{}) - return err - }, - EndLine: "diff --git a/file.txt b/file.txt\n", - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - if err := test.Parse(p); err != nil { - t.Fatalf("unexpected error while parsing: %v", err) - } - - if test.EndLine != p.Line(0) { - t.Errorf("incorrect position after parsing\nexpected: %q\n actual: %q", test.EndLine, p.Line(0)) - } - }) - } -} - -func TestParseNextFileHeader(t *testing.T) { - tests := map[string]struct { - Input string - Output *File - Preamble string - Err bool - }{ - "gitHeader": { - Input: `commit 1acbae563cd6ef5750a82ee64e116c6eb065cb94 -Author: Morton Haypenny <mhaypenny@example.com> -Date: Tue Apr 2 22:30:00 2019 -0700 - - This is a sample commit message. - -diff --git a/file.txt b/file.txt -index cc34da1..1acbae5 100644 ---- a/file.txt -+++ b/file.txt -@@ -1,3 +1,4 @@ -`, - Output: &File{ - OldName: "file.txt", - NewName: "file.txt", - OldMode: os.FileMode(0100644), - OldOIDPrefix: "cc34da1", - NewOIDPrefix: "1acbae5", - }, - Preamble: `commit 1acbae563cd6ef5750a82ee64e116c6eb065cb94 -Author: Morton Haypenny <mhaypenny@example.com> -Date: Tue Apr 2 22:30:00 2019 -0700 - - This is a sample commit message. - -`, - }, - "traditionalHeader": { - Input: ` ---- file.txt 2019-04-01 22:58:14.833597918 -0700 -+++ file.txt 2019-04-01 22:58:14.833597918 -0700 -@@ -1,3 +1,4 @@ -`, - Output: &File{ - OldName: "file.txt", - NewName: "file.txt", - }, - Preamble: "\n", - }, - "noHeaders": { - Input: ` -this is a line -this is another line ---- could this be a header? -nope, it's just some dashes -`, - Output: nil, - Preamble: ` -this is a line -this is another line ---- could this be a header? -nope, it's just some dashes -`, - }, - "detatchedFragmentLike": { - Input: ` -a wild fragment appears? -@@ -1,3 +1,4 ~1,5 @@ -`, - Output: nil, - Preamble: ` -a wild fragment appears? -@@ -1,3 +1,4 ~1,5 @@ -`, - }, - "detatchedFragment": { - Input: ` -a wild fragment appears? -@@ -1,3 +1,4 @@ -`, - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - f, pre, err := p.ParseNextFileHeader() - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing next file header, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("unexpected error parsing next file header: %v", err) - } - - if test.Preamble != pre { - t.Errorf("incorrect preamble\nexpected: %q\n actual: %q", test.Preamble, pre) - } - if !reflect.DeepEqual(test.Output, f) { - t.Errorf("incorrect file\nexpected: %+v\n actual: %+v", test.Output, f) - } - }) - } -} - -func TestParse(t *testing.T) { - textFragments := []*TextFragment{ - { - OldPosition: 3, - OldLines: 6, - NewPosition: 3, - NewLines: 8, - Comment: "fragment 1", - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 1\n"}, - {OpDelete, "old line 2\n"}, - {OpContext, "context line\n"}, - {OpAdd, "new line 1\n"}, - {OpAdd, "new line 2\n"}, - {OpAdd, "new line 3\n"}, - {OpContext, "context line\n"}, - {OpDelete, "old line 3\n"}, - {OpAdd, "new line 4\n"}, - {OpAdd, "new line 5\n"}, - }, - LinesAdded: 5, - LinesDeleted: 3, - LeadingContext: 1, - }, - { - OldPosition: 31, - OldLines: 2, - NewPosition: 33, - NewLines: 2, - Comment: "fragment 2", - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 4\n"}, - {OpAdd, "new line 6\n"}, - }, - LinesAdded: 1, - LinesDeleted: 1, - LeadingContext: 1, - }, - } - - textPreamble := `commit 5d9790fec7d95aa223f3d20936340bf55ff3dcbe -Author: Morton Haypenny <mhaypenny@example.com> -Date: Tue Apr 2 22:55:40 2019 -0700 - - A file with multiple fragments. - - The content is arbitrary. - -` - - binaryPreamble := `commit 5d9790fec7d95aa223f3d20936340bf55ff3dcbe -Author: Morton Haypenny <mhaypenny@example.com> -Date: Tue Apr 2 22:55:40 2019 -0700 - - A binary file with the first 10 fibonacci numbers. - -` - tests := map[string]struct { - InputFile string - Output []*File - Preamble string - Err bool - }{ - "oneFile": { - InputFile: "testdata/one_file.patch", - Output: []*File{ - { - OldName: "dir/file1.txt", - NewName: "dir/file1.txt", - OldMode: os.FileMode(0100644), - OldOIDPrefix: "ebe9fa54", - NewOIDPrefix: "fe103e1d", - TextFragments: textFragments, - }, - }, - Preamble: textPreamble, - }, - "twoFiles": { - InputFile: "testdata/two_files.patch", - Output: []*File{ - { - OldName: "dir/file1.txt", - NewName: "dir/file1.txt", - OldMode: os.FileMode(0100644), - OldOIDPrefix: "ebe9fa54", - NewOIDPrefix: "fe103e1d", - TextFragments: textFragments, - }, - { - OldName: "dir/file2.txt", - NewName: "dir/file2.txt", - OldMode: os.FileMode(0100644), - OldOIDPrefix: "417ebc70", - NewOIDPrefix: "67514b7f", - TextFragments: textFragments, - }, - }, - Preamble: textPreamble, - }, - "noFiles": { - InputFile: "testdata/no_files.patch", - Output: nil, - Preamble: textPreamble, - }, - "newBinaryFile": { - InputFile: "testdata/new_binary_file.patch", - Output: []*File{ - { - OldName: "", - NewName: "dir/ten.bin", - NewMode: os.FileMode(0100644), - OldOIDPrefix: "0000000000000000000000000000000000000000", - NewOIDPrefix: "77b068ba48c356156944ea714740d0d5ca07bfec", - IsNew: true, - IsBinary: true, - BinaryFragment: &BinaryFragment{ - Method: BinaryPatchLiteral, - Size: 40, - Data: fib(10, binary.BigEndian), - }, - ReverseBinaryFragment: &BinaryFragment{ - Method: BinaryPatchLiteral, - Size: 0, - Data: []byte{}, - }, - }, - }, - Preamble: binaryPreamble, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - f, err := os.Open(test.InputFile) - if err != nil { - t.Fatalf("unexpected error opening input file: %v", err) - } - - files, pre, err := Parse(f) - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing patch, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("unexpected error parsing patch: %v", err) - } - - if len(test.Output) != len(files) { - t.Fatalf("incorrect number of parsed files: expected %d, actual %d", len(test.Output), len(files)) - } - if test.Preamble != pre { - t.Errorf("incorrect preamble\nexpected: %q\n actual: %q", test.Preamble, pre) - } - for i := range test.Output { - if !reflect.DeepEqual(test.Output[i], files[i]) { - exp, _ := json.MarshalIndent(test.Output[i], "", " ") - act, _ := json.MarshalIndent(files[i], "", " ") - t.Errorf("incorrect file at position %d\nexpected: %s\n actual: %s", i, exp, act) - } - } - }) - } -} - -func newTestParser(input string, init bool) *parser { - p := newParser(bytes.NewBufferString(input)) - if init { - _ = p.Next() - } - return p -} diff --git a/pkg/gitdiff/patch_header_test.go b/pkg/gitdiff/patch_header_test.go deleted file mode 100644 index c8559b0..0000000 --- a/pkg/gitdiff/patch_header_test.go +++ /dev/null @@ -1,590 +0,0 @@ -package gitdiff - -import ( - "testing" - "time" -) - -func TestParsePatchDate(t *testing.T) { - expected := time.Date(2020, 4, 9, 8, 7, 6, 0, time.UTC) - - tests := map[string]struct { - Input string - Output time.Time - Err interface{} - }{ - "default": { - Input: "Thu Apr 9 01:07:06 2020 -0700", - Output: expected, - }, - "defaultLocal": { - Input: "Thu Apr 9 01:07:06 2020", - Output: time.Date(2020, 4, 9, 1, 7, 6, 0, time.Local), - }, - "iso": { - Input: "2020-04-09 01:07:06 -0700", - Output: expected, - }, - "isoStrict": { - Input: "2020-04-09T01:07:06-07:00", - Output: expected, - }, - "rfc": { - Input: "Thu, 9 Apr 2020 01:07:06 -0700", - Output: expected, - }, - "short": { - Input: "2020-04-09", - Output: time.Date(2020, 4, 9, 0, 0, 0, 0, time.Local), - }, - "raw": { - Input: "1586419626 -0700", - Output: expected, - }, - "unix": { - Input: "1586419626", - Output: expected, - }, - "unknownFormat": { - Input: "4/9/2020 01:07:06 PDT", - Err: "unknown date format", - }, - "empty": { - Input: "", - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - d, err := ParsePatchDate(test.Input) - if test.Err != nil { - assertError(t, test.Err, err, "parsing date") - return - } - if err != nil { - t.Fatalf("unexpected error parsing date: %v", err) - } - if !test.Output.Equal(d) { - t.Errorf("incorrect parsed date: expected %v, actual %v", test.Output, d) - } - }) - } -} - -func TestParsePatchHeader(t *testing.T) { - expectedSHA := "61f5cd90bed4d204ee3feb3aa41ee91d4734855b" - expectedIdentity := &PatchIdentity{ - Name: "Morton Haypenny", - Email: "mhaypenny@example.com", - } - expectedDate := time.Date(2020, 04, 11, 15, 21, 23, 0, time.FixedZone("PDT", -7*60*60)) - expectedTitle := "A sample commit to test header parsing" - expectedEmojiOneLineTitle := "๐ค Enabling auto-merging" - expectedEmojiMultiLineTitle := "[IA64] Put ia64 config files on the Uwe Kleine-Kรถnig diet" - expectedBody := "The medium format shows the body, which\nmay wrap on to multiple lines.\n\nAnother body line." - expectedBodyAppendix := "CC: Joe Smith <joe.smith@company.com>" - - tests := map[string]struct { - Input string - Options []PatchHeaderOption - Header PatchHeader - Err interface{} - }{ - "prettyShort": { - Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny <mhaypenny@example.com> - - A sample commit to test header parsing -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - Title: expectedTitle, - }, - }, - "prettyMedium": { - Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny <mhaypenny@example.com> -Date: Sat Apr 11 15:21:23 2020 -0700 - - A sample commit to test header parsing - - The medium format shows the body, which - may wrap on to multiple lines. - - Another body line. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "prettyFull": { - Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny <mhaypenny@example.com> -Commit: Morton Haypenny <mhaypenny@example.com> - - A sample commit to test header parsing - - The medium format shows the body, which - may wrap on to multiple lines. - - Another body line. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - Committer: expectedIdentity, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "prettyFuller": { - Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny <mhaypenny@example.com> -AuthorDate: Sat Apr 11 15:21:23 2020 -0700 -Commit: Morton Haypenny <mhaypenny@example.com> -CommitDate: Sat Apr 11 15:21:23 2020 -0700 - - A sample commit to test header parsing - - The medium format shows the body, which - may wrap on to multiple lines. - - Another body line. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Committer: expectedIdentity, - CommitterDate: expectedDate, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "prettyAppendix": { - Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny <mhaypenny@example.com> -AuthorDate: Sat Apr 11 15:21:23 2020 -0700 -Commit: Morton Haypenny <mhaypenny@example.com> -CommitDate: Sat Apr 11 15:21:23 2020 -0700 - - A sample commit to test header parsing - - The medium format shows the body, which - may wrap on to multiple lines. - - Another body line. - --- - CC: Joe Smith <joe.smith@company.com> -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Committer: expectedIdentity, - CommitterDate: expectedDate, - Title: expectedTitle, - Body: expectedBody + "\n---\n" + expectedBodyAppendix, - }, - }, - "mailbox": { - Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 -From: Morton Haypenny <mhaypenny@example.com> -Date: Sat, 11 Apr 2020 15:21:23 -0700 -Subject: [PATCH] A sample commit to test header parsing - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "mailboxPatchOnly": { - Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 -From: Morton Haypenny <mhaypenny@example.com> -Date: Sat, 11 Apr 2020 15:21:23 -0700 -Subject: [PATCH] [BUG-123] A sample commit to test header parsing - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. -`, - Options: []PatchHeaderOption{ - WithSubjectCleanMode(SubjectCleanPatchOnly), - }, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: "[BUG-123] " + expectedTitle, - Body: expectedBody, - }, - }, - "mailboxEmojiOneLine": { - Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 -From: Morton Haypenny <mhaypenny@example.com> -Date: Sat, 11 Apr 2020 15:21:23 -0700 -Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20Enabling=20auto-merging?= - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: expectedEmojiOneLineTitle, - Body: expectedBody, - }, - }, - "mailboxEmojiMultiLine": { - Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 -From: Morton Haypenny <mhaypenny@example.com> -Date: Sat, 11 Apr 2020 15:21:23 -0700 -Subject: [PATCH] =?UTF-8?q?[IA64]=20Put=20ia64=20config=20files=20on=20the=20?= - =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20diet?= - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: expectedEmojiMultiLineTitle, - Body: expectedBody, - }, - }, - "mailboxRFC5322SpecialCharacters": { - Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 -From: "dependabot[bot]" <12345+dependabot[bot]@users.noreply.github.com> -Date: Sat, 11 Apr 2020 15:21:23 -0700 -Subject: [PATCH] A sample commit to test header parsing - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: &PatchIdentity{ - Name: "dependabot[bot]", - Email: "12345+dependabot[bot]@users.noreply.github.com", - }, - AuthorDate: expectedDate, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "mailboxAppendix": { - Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 -From: Morton Haypenny <mhaypenny@example.com> -Date: Sat, 11 Apr 2020 15:21:23 -0700 -Subject: [PATCH] A sample commit to test header parsing - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. ---- -CC: Joe Smith <joe.smith@company.com> -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: expectedTitle, - Body: expectedBody, - BodyAppendix: expectedBodyAppendix, - }, - }, - "mailboxMinimalNoName": { - Input: `From: <mhaypenny@example.com> -Subject: [PATCH] A sample commit to test header parsing - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. -`, - Header: PatchHeader{ - Author: &PatchIdentity{expectedIdentity.Email, expectedIdentity.Email}, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "mailboxMinimal": { - Input: `From: Morton Haypenny <mhaypenny@example.com> -Subject: [PATCH] A sample commit to test header parsing - -The medium format shows the body, which -may wrap on to multiple lines. - -Another body line. -`, - Header: PatchHeader{ - Author: expectedIdentity, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "unwrapTitle": { - Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny <mhaypenny@example.com> -Date: Sat Apr 11 15:21:23 2020 -0700 - - A sample commit to test header parsing with a long - title that is wrapped. -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: expectedTitle + " with a long title that is wrapped.", - }, - }, - "normalizeBodySpace": { - Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny <mhaypenny@example.com> -Date: Sat Apr 11 15:21:23 2020 -0700 - - A sample commit to test header parsing - - - The medium format shows the body, which - may wrap on to multiple lines. - - - Another body line. - - -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - AuthorDate: expectedDate, - Title: expectedTitle, - Body: expectedBody, - }, - }, - "ignoreLeadingBlankLines": { - Input: ` - -` + " " + ` -commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b -Author: Morton Haypenny <mhaypenny@example.com> - - A sample commit to test header parsing -`, - Header: PatchHeader{ - SHA: expectedSHA, - Author: expectedIdentity, - Title: expectedTitle, - }, - }, - "emptyHeader": { - Input: "", - Header: PatchHeader{}, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - h, err := ParsePatchHeader(test.Input, test.Options...) - if test.Err != nil { - assertError(t, test.Err, err, "parsing patch header") - return - } - if err != nil { - t.Fatalf("unexpected error parsing patch header: %v", err) - } - if h == nil { - t.Fatalf("expected non-nil header, but got nil") - } - - exp := test.Header - act := *h - - if exp.SHA != act.SHA { - t.Errorf("incorrect parsed SHA: expected %q, actual %q", exp.SHA, act.SHA) - } - - assertPatchIdentity(t, "author", exp.Author, act.Author) - if !exp.AuthorDate.Equal(act.AuthorDate) { - t.Errorf("incorrect parsed author date: expected %v, but got %v", exp.AuthorDate, act.AuthorDate) - } - - assertPatchIdentity(t, "committer", exp.Committer, act.Committer) - if !exp.CommitterDate.Equal(act.CommitterDate) { - t.Errorf("incorrect parsed committer date: expected %v, but got %v", exp.CommitterDate, act.CommitterDate) - } - - if exp.Title != act.Title { - t.Errorf("incorrect parsed title:\n expected: %q\n actual: %q", exp.Title, act.Title) - } - if exp.Body != act.Body { - t.Errorf("incorrect parsed body:\n expected: %q\n actual: %q", exp.Body, act.Body) - } - if exp.BodyAppendix != act.BodyAppendix { - t.Errorf("incorrect parsed body appendix:\n expected: %q\n actual: %q", - exp.BodyAppendix, act.BodyAppendix) - } - }) - } -} - -func assertPatchIdentity(t *testing.T, kind string, exp, act *PatchIdentity) { - switch { - case exp == nil && act == nil: - case exp == nil && act != nil: - t.Errorf("incorrect parsed %s: expected nil, but got %+v", kind, act) - case exp != nil && act == nil: - t.Errorf("incorrect parsed %s: expected %+v, but got nil", kind, exp) - case exp.Name != act.Name || exp.Email != act.Email: - t.Errorf("incorrect parsed %s, expected %+v, bot got %+v", kind, exp, act) - } -} - -func TestCleanSubject(t *testing.T) { - expectedSubject := "A sample commit to test header parsing" - - tests := map[string]struct { - Input string - Mode SubjectCleanMode - Prefix string - Subject string - }{ - "CleanAll/noPrefix": { - Input: expectedSubject, - Mode: SubjectCleanAll, - Subject: expectedSubject, - }, - "CleanAll/patchPrefix": { - Input: "[PATCH] " + expectedSubject, - Mode: SubjectCleanAll, - Prefix: "[PATCH] ", - Subject: expectedSubject, - }, - "CleanAll/patchPrefixNoSpace": { - Input: "[PATCH]" + expectedSubject, - Mode: SubjectCleanAll, - Prefix: "[PATCH]", - Subject: expectedSubject, - }, - "CleanAll/patchPrefixContent": { - Input: "[PATCH 3/7] " + expectedSubject, - Mode: SubjectCleanAll, - Prefix: "[PATCH 3/7] ", - Subject: expectedSubject, - }, - "CleanAll/spacePrefix": { - Input: " " + expectedSubject, - Mode: SubjectCleanAll, - Subject: expectedSubject, - }, - "CleanAll/replyLowerPrefix": { - Input: "re: " + expectedSubject, - Mode: SubjectCleanAll, - Prefix: "re: ", - Subject: expectedSubject, - }, - "CleanAll/replyMixedPrefix": { - Input: "Re: " + expectedSubject, - Mode: SubjectCleanAll, - Prefix: "Re: ", - Subject: expectedSubject, - }, - "CleanAll/replyCapsPrefix": { - Input: "RE: " + expectedSubject, - Mode: SubjectCleanAll, - Prefix: "RE: ", - Subject: expectedSubject, - }, - "CleanAll/replyDoublePrefix": { - Input: "Re: re: " + expectedSubject, - Mode: SubjectCleanAll, - Prefix: "Re: re: ", - Subject: expectedSubject, - }, - "CleanAll/noPrefixSubjectHasRe": { - Input: "Reimplement parsing", - Mode: SubjectCleanAll, - Subject: "Reimplement parsing", - }, - "CleanAll/patchPrefixSubjectHasRe": { - Input: "[PATCH 1/2] Reimplement parsing", - Mode: SubjectCleanAll, - Prefix: "[PATCH 1/2] ", - Subject: "Reimplement parsing", - }, - "CleanAll/unclosedPrefix": { - Input: "[Just to annoy people", - Mode: SubjectCleanAll, - Subject: "[Just to annoy people", - }, - "CleanAll/multiplePrefix": { - Input: " Re:Re: [PATCH 1/2][DRAFT] " + expectedSubject + " ", - Mode: SubjectCleanAll, - Prefix: "Re:Re: [PATCH 1/2][DRAFT] ", - Subject: expectedSubject, - }, - "CleanPatchOnly/patchPrefix": { - Input: "[PATCH] " + expectedSubject, - Mode: SubjectCleanPatchOnly, - Prefix: "[PATCH] ", - Subject: expectedSubject, - }, - "CleanPatchOnly/mixedPrefix": { - Input: "[PATCH] [TICKET-123] " + expectedSubject, - Mode: SubjectCleanPatchOnly, - Prefix: "[PATCH] ", - Subject: "[TICKET-123] " + expectedSubject, - }, - "CleanPatchOnly/multiplePrefix": { - Input: "Re:Re: [PATCH 1/2][DRAFT] " + expectedSubject, - Mode: SubjectCleanPatchOnly, - Prefix: "Re:Re: [PATCH 1/2]", - Subject: "[DRAFT] " + expectedSubject, - }, - "CleanWhitespace/leadingSpace": { - Input: " [PATCH] " + expectedSubject, - Mode: SubjectCleanWhitespace, - Subject: "[PATCH] " + expectedSubject, - }, - "CleanWhitespace/trailingSpace": { - Input: "[PATCH] " + expectedSubject + " ", - Mode: SubjectCleanWhitespace, - Subject: "[PATCH] " + expectedSubject, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - prefix, subject := cleanSubject(test.Input, test.Mode) - if prefix != test.Prefix { - t.Errorf("incorrect prefix: expected %q, actual %q", test.Prefix, prefix) - } - if subject != test.Subject { - t.Errorf("incorrect subject: expected %q, actual %q", test.Subject, subject) - } - }) - } -} diff --git a/pkg/gitdiff/patch_identity_test.go b/pkg/gitdiff/patch_identity_test.go deleted file mode 100644 index f15fe38..0000000 --- a/pkg/gitdiff/patch_identity_test.go +++ /dev/null @@ -1,127 +0,0 @@ -package gitdiff - -import ( - "testing" -) - -func TestParsePatchIdentity(t *testing.T) { - tests := map[string]struct { - Input string - Output PatchIdentity - Err interface{} - }{ - "simple": { - Input: "Morton Haypenny <mhaypenny@example.com>", - Output: PatchIdentity{ - Name: "Morton Haypenny", - Email: "mhaypenny@example.com", - }, - }, - "extraWhitespace": { - Input: "\t Morton Haypenny \r\n<mhaypenny@example.com> ", - Output: PatchIdentity{ - Name: "Morton Haypenny", - Email: "mhaypenny@example.com", - }, - }, - "trailingCharacters": { - Input: "Morton Haypenny <mhaypenny@example.com> II", - Output: PatchIdentity{ - Name: "Morton Haypenny II", - Email: "mhaypenny@example.com", - }, - }, - "onlyEmail": { - Input: "mhaypenny@example.com", - Output: PatchIdentity{ - Name: "mhaypenny@example.com", - Email: "mhaypenny@example.com", - }, - }, - "onlyEmailInBrackets": { - Input: "<mhaypenny@example.com>", - Output: PatchIdentity{ - Name: "mhaypenny@example.com", - Email: "mhaypenny@example.com", - }, - }, - "rfc5322SpecialCharacters": { - Input: `"dependabot[bot]" <12345+dependabot[bot]@users.noreply.github.com>`, - Output: PatchIdentity{ - Name: "dependabot[bot]", - Email: "12345+dependabot[bot]@users.noreply.github.com", - }, - }, - "rfc5322QuotedPairs": { - Input: `"Morton \"Old-Timer\" Haypenny" <"mhaypenny\+[1900]"@example.com> (III \(PhD\))`, - Output: PatchIdentity{ - Name: `Morton "Old-Timer" Haypenny (III (PhD))`, - Email: "mhaypenny+[1900]@example.com", - }, - }, - "rfc5322QuotedPairsOutOfContext": { - Input: `Morton \\Backslash Haypenny <mhaypenny@example.com>`, - Output: PatchIdentity{ - Name: `Morton \\Backslash Haypenny`, - Email: "mhaypenny@example.com", - }, - }, - "emptyEmail": { - Input: "Morton Haypenny <>", - Output: PatchIdentity{ - Name: "Morton Haypenny", - Email: "", - }, - }, - "unclosedEmail": { - Input: "Morton Haypenny <mhaypenny@example.com", - Output: PatchIdentity{ - Name: "Morton Haypenny", - Email: "mhaypenny@example.com", - }, - }, - "bogusEmail": { - Input: "Morton Haypenny <mhaypenny>", - Output: PatchIdentity{ - Name: "Morton Haypenny", - Email: "mhaypenny", - }, - }, - "bogusEmailWithWhitespace": { - Input: "Morton Haypenny < mhaypenny >", - Output: PatchIdentity{ - Name: "Morton Haypenny", - Email: "mhaypenny", - }, - }, - "missingEmail": { - Input: "Morton Haypenny", - Err: "invalid identity", - }, - "missingNameAndEmptyEmail": { - Input: "<>", - Err: "invalid identity", - }, - "empty": { - Input: "", - Err: "invalid identity", - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - id, err := ParsePatchIdentity(test.Input) - if test.Err != nil { - assertError(t, test.Err, err, "parsing identity") - return - } - if err != nil { - t.Fatalf("unexpected error parsing identity: %v", err) - } - - if test.Output != id { - t.Errorf("incorrect identity: expected %#v, actual %#v", test.Output, id) - } - }) - } -} diff --git a/pkg/gitdiff/testdata/apply/bin.go b/pkg/gitdiff/testdata/apply/bin.go deleted file mode 100644 index e34f06b..0000000 --- a/pkg/gitdiff/testdata/apply/bin.go +++ /dev/null @@ -1,124 +0,0 @@ -//go:build ignore - -// bin.go is a helper CLI to manipulate binary diff data for testing purposes. -// It can decode patches generated by git using the standard parsing functions -// or it can encode binary data back into the format expected by Git. It -// operates on stdin writes results (possibly binary) to stdout. - -package main - -import ( - "bytes" - "compress/zlib" - "encoding/binary" - "flag" - "io/ioutil" - "log" - "os" - "strings" - - "github.com/bluekeyes/go-gitdiff/gitdiff" -) - -var ( - b85Powers = []uint32{52200625, 614125, 7225, 85, 1} - b85Alpha = []byte( - "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "!#$%&()*+-;<=>?@^_`{|}~", - ) -) - -var mode string - -func base85Encode(data []byte) []byte { - chunks, remaining := len(data)/4, len(data)%4 - if remaining > 0 { - data = append(data, make([]byte, 4-remaining)...) - chunks++ - } - - var n int - out := make([]byte, 5*chunks) - - for i := 0; i < len(data); i += 4 { - v := binary.BigEndian.Uint32(data[i : i+4]) - for j := 0; j < 5; j++ { - p := v / b85Powers[j] - out[n+j] = b85Alpha[p] - v -= b85Powers[j] * p - } - n += 5 - } - - return out -} - -func compress(data []byte) ([]byte, error) { - var b bytes.Buffer - w := zlib.NewWriter(&b) - - if _, err := w.Write(data); err != nil { - return nil, err - } - if err := w.Close(); err != nil { - return nil, err - } - - return b.Bytes(), nil -} - -func wrap(data []byte) string { - var s strings.Builder - for i := 0; i < len(data); i += 52 { - c := 52 - if c > len(data)-i { - c = len(data) - i - } - b := (c / 5) * 4 - - if b <= 26 { - s.WriteByte(byte('A' + b - 1)) - } else { - s.WriteByte(byte('a' + b - 27)) - } - s.Write(data[i : i+c]) - s.WriteByte('\n') - } - return s.String() -} - -func init() { - flag.StringVar(&mode, "mode", "parse", "operation mode, one of 'parse' or 'encode'") -} - -func main() { - flag.Parse() - - switch mode { - case "parse": - files, _, err := gitdiff.Parse(os.Stdin) - if err != nil { - log.Fatalf("failed to parse file: %v", err) - } - if len(files) != 1 { - log.Fatalf("patch contains more than one file: %d", len(files)) - } - if files[0].BinaryFragment == nil { - log.Fatalf("patch file does not contain a binary fragment") - } - os.Stdout.Write(files[0].BinaryFragment.Data) - - case "encode": - data, err := ioutil.ReadAll(os.Stdin) - if err != nil { - log.Fatalf("failed to read input: %v", err) - } - data, err = compress(data) - if err != nil { - log.Fatalf("failed to compress data: %v", err) - } - os.Stdout.WriteString(wrap(base85Encode(data))) - - default: - log.Fatalf("unknown mode: %s", mode) - } -} diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error.src b/pkg/gitdiff/testdata/apply/bin_fragment_delta_error.src Binary files differdeleted file mode 100644 index d4edf89..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error.src +++ /dev/null diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_dst_size.patch b/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_dst_size.patch deleted file mode 100644 index 6d5bb42..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_dst_size.patch +++ /dev/null @@ -1,5 +0,0 @@ -diff --git a/gitdiff/testdata/apply/bin_fragment_delta_error.src b/gitdiff/testdata/apply/bin_fragment_delta_error.src -GIT binary patch -delta 18 -fc${itY+{<=z`_4AtEhVK$zKyatN;N30RR6$D+j^= - diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_add.patch b/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_add.patch deleted file mode 100644 index b8c1835..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_add.patch +++ /dev/null @@ -1,5 +0,0 @@ -diff --git a/gitdiff/testdata/apply/bin_fragment_delta_error.src b/gitdiff/testdata/apply/bin_fragment_delta_error.src -GIT binary patch -delta 11 -Xc${itY+{_?z`_4As|XMP0RR6K8UwQc - diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_copy.patch b/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_copy.patch deleted file mode 100644 index 8db8f84..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_copy.patch +++ /dev/null @@ -1,5 +0,0 @@ -diff --git a/gitdiff/testdata/apply/bin_fragment_delta_error.src b/gitdiff/testdata/apply/bin_fragment_delta_error.src -GIT binary patch -delta 17 -fc${itY+{_?z`_4AtEhVK$zKya00961|Nl5!2ZsOv - diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_src_size.patch b/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_src_size.patch deleted file mode 100644 index 29cb26b..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_error_src_size.patch +++ /dev/null @@ -1,5 +0,0 @@ -diff --git a/gitdiff/testdata/apply/bin_fragment_delta_error.src b/gitdiff/testdata/apply/bin_fragment_delta_error.src -GIT binary patch -delta 18 -fc${itYGRz=z`_4AtEhVK$zKyatN;N30RR6$EeFB? - diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.out b/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.out Binary files differdeleted file mode 100644 index f3386d1..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.out +++ /dev/null diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.patch b/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.patch deleted file mode 100644 index 1801ef2..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/gitdiff/testdata/apply/bin_fragment_delta_modify.src b/gitdiff/testdata/apply/bin_fragment_delta_modify.src -GIT binary patch -delta 172 -zcmV;d08{^f2)qc8AP{I3VQ>J`s>wb0HU+h#6w8q?tUO~cHmDjZi2<8yZ9XmKhhMdo -zWu(4bg|8QwzZ|1e*rL4P#)`Fen<n~ik=E?$qG6?hzJ6$u{l5W#?uwHb0q6w)00000 -zlLZ3%0RfW%1N%UMJ{~Z~0@X${&1Kk#98tb3==a{J7A;`O`v&<T@514_mvMTz72b#n -atf$#NLoPbNe?RPFJVt1aCFGoQbiKD!OHgJ2 - -delta 112 -zcmV-$0FVE?2!IHXAP~DY<7&llQfwqYA%tL<sR@xVtUMD;+4ZG>XTQ5=J2y;^BfB}4 -zWkisH791|vOVl5e-@^VLX0s~Ky_UyN!3;CgPr>Edj0j+0gOSwSsFsr$0q6zUJph<q -SlLZ3%0XmZb1N#I__7UCuR5Dxu - diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.src b/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.src Binary files differdeleted file mode 100644 index fb85478..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify.src +++ /dev/null diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify_large.out b/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify_large.out Binary files differdeleted file mode 100644 index f0f7f14..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify_large.out +++ /dev/null diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify_large.patch b/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify_large.patch deleted file mode 100644 index 093936b..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify_large.patch +++ /dev/null @@ -1,166 +0,0 @@ -diff --git a/gitdiff/testdata/apply/bin_fragment_delta_modify_large.src b/gitdiff/testdata/apply/bin_fragment_delta_modify_large.src -GIT binary patch -delta 4145 -zcmV-15YF#_fCzwq2!NCU6n}UD@BJ(nwumRXTBWU&(r44U#UTR?Hg2j#E9tcD8>JCY -zqz<L)JrNXpEfw|b8Ts&UEkO5+T?jiM$x7@_P2&_*&`$=fcypBBj#$(pjJ9|+w!nF; -z*sgN!^;$QEf?3|e>)g`N&ViW9W6D7kX7GX{y{m=JvFi1-r`PEE?SE&^2StK}qz5hC -zom0ywdCWuNb#YXdd0%FMNHft!FTER$>uzu5gxdoGBy789raJBW7jAhN2TWFL{P%2l -z|AX{}Jz8U}Y*X|~=?4<;F4)94!-e?w)#D0h8n1_ORWNCOC&7=!U0MP3<v=_v9C5!i -z0Q+7#pUXRc?6%;cFn?F`n#;%_dGwni+^Ev;mF)3qj28^tfxPMqDV12HP;vJ_p9F#w -z{re$r!khX1Grt6PEg!>BI0~M)pZ-cf6aFkVFzO&JOkcv7FeEq|)DcBDAP&_&ZgBk* -zVp(I^5-bN3L{~g{bHnkWX%0Hj02~njkKX8Zz%Ih#=LBD%Pk%TkW4ize_HweE#@_-2 -zvpyE#e@^n#rRGx;O84LB3bMdrxdv%Gkc)ZQq%8pkxT9b*)}Z&t5bibZ0)8H8T33vN -zgTj)j_%wz13x+TZ6LgdupD^ke2!n7E-YZ%8n3OTzK5*T(BH>ltfU|QJ7VTAu<e}on -z$=JJjjciFFN`Fzsxf-MARHfr7D9c#x?{62mGRmgzrR~VD+Ec3xhX?ouWpC(VJF31{ -zSg`N(Bv@0v75=Jj5L%(L+)rQK7Yqo!ZI;@6S<+%;8n*To-C%h>r}ah?0sC%ZUY?<b -zv(0AQ|7cLp<eKKWxX)Y#(4*sOJ(f!elXc4>&xwkEUw@Y9LqO1~eF>>5cDlg_YxuF| -zZ58JVlu7IBfP1@TDmG;<{X>(&*Hy<j=OVk<Z{4Xw!q_uh3PF;mQ=%{@DP($Ym^O7u -z()CP&Lg$k9$86TRX~S*o)PMp4ltJ3>C-7zqRrY~#3W>hP8@a&jwYi_$k(j`D$Ta97 -z{(rL4B7Ysa#+5QC40p?w_V}r&G%{W$)8R1P`wet5K>`4D&EanFW{d2mOB<F_6i4{2 -zyvNjwqpz2xNywg~atQE~7i+4HXtp*BZ=iZbxqB9%ln@_KVIKuO(nLG^6V%DDaJYn* -z=!{Jo%`{rQ1*~_S3Xt4d{uL-EROqk|1qV~gXMd@K!*vHg@UsOgfcNC~T%s^yNa-mE -zWwvGu5f1Z&pe6o5bGG4F@r5(pTx6;)9Ly8(reL*<OVspK=%BY6Le~m;0dvr`0#=GZ -zlA<Vi?w~V5RN|C0iy|D|@2CGptYlBJMz31?1p!JP^z~%w&3`BBU&UCo@6HFkrK-3O -z^M6Vy;CO*>vm~hJviTXh@a)Qp^TpF9X}vEVN-{LA%5X<MH)9ZCktsL5)O9)!?Qy`S -zDd4*FDIj>p^*>%23c&{6HgPH4ahb@257yLNuno+(_9IJ!cgw97b*@K~X-9f8rdsd` -zOSj362)!mBsX%<QkLK_a4;5C`Hw&r*C4c$CJwCk3vNJG1z*ZUK_s-To!tlwRObW19 -zUka<y!0g)DN^Vs$_rw9OJP`AO*l3*zd7z+1UHYUg7uw9?U+{6;pts4(?Z!@3C6;>A -zQ*StV4WzVHG#+*IwPf7@BwNAUN{Tre0&7KHK8Gq6W2Jeqe%S(>+{1HM$cFn>J%6m& -z|8$kpBb=Dxh6$MwDCzl1g;Y`~f7F-wEny-#iI1X?l(D;Z$PLR3jay0@l4S5PR8fS< -zi+>Hek8mDV9ItDt3}cF;v-yN79ZUwT1^LyF1n$Cy%gt_C&r9r*A*)&$ZFl<eghAvH -zRkrj-L9@*P`M#b14DP@YWqKrGihs`_$9}?b&`hgRiub41qZ?7&Nh%}HpP3Tbttvv5 -zq=W1Nc?DQo<|}6{xbpW%2@<O6f0JU{G6JrwI_yfvDsdp$CDKVJe{UP|{F2$LMyq;S -z;6*a3u>HnVf=mg#Q%sK{dyD8$2z{ndd#G^c?_~0mb!M$7ZxU$373E=vV}GR5OrWDm -zBsRhxx$#Ql_U#b2h}uPg{qm53MhlGO!F^=m@8@Ie88^<EsYD1;{veTT&+b|bRnb#@ -z2Am8hM&Q?IXN2#P3~!urpHr8+JIMR`C~)B}()1`g{Nu|NSpJQdrZ#t5ZDCpLl)y5a -zI3es-`NqV4QL_t{&2)4pvwsR>`%?=q2+>^o91FPtaKgX{mUR_AEr9NwT^_^@8>UHx -z6Vql9ovz7$NpnPl5QlqsKP0|}EskXfTz-@ZpBlsI-~?B-4%w_GY9s9?ln=!A8wNMf -z=;eAIwp6&0nZ9Qq({C*2AXx<ZqTxd)R(xsn?F4+P$}#JS<u|x9n19vknU^?{8C$(2 -z{+;MK!HljtP!Bu31=DpsC-~V`aJ>KEGCjGa)2K^@ryP2!6dWiRy0M0vL*145f@BzR -z`IXs~3pGOq&;GIFDC<KN4u<vU;>=$JbDmK$C`A~nS$@*@hY$2e@kN0E;7jK@*TzW0 -z2FmwjqM0G-dfMDB3x5@pycb${TTJ7dzu+teFC9mUiSr(jrvQ~;sj`>uoen9{iXP5; -zbF9`-K065Zx&Tv2gK4wf8(U++M31oGlTiV$(^)qux9<b>7HP~_mSNPtqZA#7xOo;Q -zc-B?N(jYE1ix_L{M|cpCS4s5I3Tx_Hh1#!O-iBP5iS>iM{C~ZUez^pglqH5IAdOAD -zE;AjwjL)_IsQU6y4t4Uc9KX<!`vlPxjFRGAG1tyHS7KLyRQx=Xb|!%gliE%^%h3dy -zy_B7SK7#Pnxw+(BwLgXV=mq;Xy%bzqFkM7}Ja4VdI`gUr`jY+&xsnc80&0~P<68@c -z{u<TCS!o65e}CwEOz7FcRp}Klf4OpWu~<6nq0Bfg&arHyU8C4!6fwm-i*mmh?)6iz -zKf_(OO)Qy-luDqjA>l~!BYeA;B8*wK)|cg^tiD0aN2iWzR>YnUUS9?3jKhiAKpgQ0 -zCRNTKwkeO~{pU<lXv(vu7Dx<e`Gj7IBkT6lpsco*Mt@D}KlB*lL|<QAS}Q%n%XFvg -zH*NegM<bJ@$syCdbs<RdsmXzbAZE0`((<O&d(r5^{{vn>2|S8)UYp21g#5$lGV|mN -zdQNSkH%R6}>C_cemrZCjR|-)D<8Y^P74a}>FKs&95{8d9SiTvhB4{eTUGFbTa-IbX -z8Lw1xoPPp_ZdIbl#dCzP1`N@V?eb7SizWtmm5ujG(rKZHZw$>Ozzf4E=Yf*+eH}kn -zL{&n><${iESA&t~5pz;&vs%HlLYxXMjPlLH{?*-#T4#$(P;pke+8K*f)n*P<u~mu| -zeR&;)e}Xp;P-smwSxfyE7_JA!0QRkDN~OJm4}W0Lw($YeyX)3OOY&fT$MrlC=TkO7 -zW{~(xl%jTs^n3F;k}Vc^eq7RCg8GuW-Aviu+r;$?G9+>h>SB9|8)|f;w=%OP6`nms -zdFVyjJf#&^=o+P_Y1Q{$$Aql8VqX+>=4)lx*&wB#{$tlb&SwC3E~G-pKOFXRQrRSk -zMt}Fa|4IQc;^N}stu@1BVjk>`8grvj#WVz9k#>7N?#JQZdag9deih!2aWVB}1klbo -zXKhuKy*h7m?``T}aM*}PexaGXqeZCm>ME7BQi64D>9lL0AoF2`Tzo^hNSMC9B=jT@ -zjA%viojl=gm6?1mPDg-)fy98Cb}Bdio_{dD+i;%nIJ6ZfQ^LPvl@~R#wk@K-##0ma -zj|D(^Fr8U(o(FRy$Z0FGyp@<r=6Jk;ZS~i6PLo%BfGyU%%&PK=Cd{mo$^aBm71sz9 -z!b|Dl3+8A-e+{qm)PHbh4jn6it1^fhu{8?r62V15rUxqn)Y2|@zH!vqg?{4<et$(K -zA?oQG3Vt}Nao4K3@C~cP)!cmK<q0(7iDfh<(I{qwIq$s=;ms)qU50x1eBN}%Cl9o- -zwRUox>Yam&`H8oVv>6n8UKEVec>#*NVp)YrdOPgay4SxQ!PjT#gf^PISz?!W;(=9W -zC3sT|H>d}ErTr;c8LY_P{IPZ;Wq&_a4mM`d<q|?_Y3|+P2w!A;3~GDKi<NZwt81V{ -z#<XjJk{Nh~dU&Bc4nc;%e$m9B1SEbX2GL`Mh%4|dmPXqAo_SnHQ~ydAo2pWNJNr#r -z&qMJ7Rm4cAa{Z?MBu-{<c!m#F`J8~VL}izx&JjpCwXp6YqQKH=rH`ccpMPM){}>Lu -zn^@7N(YC~q-qV~usbu?>{mD#~LNHhWdnNcaB&J>J@M)=+i^{*SwmS-XE-ywoYoZ3U -zdb4|M(!Ok$LY!K2m*Wjy>w_)zTm#k_g&J$V<PC_-!ZtfnOT~DwbQAMPmaiNnPYa}E -zC0qUqV#JtW?*@6Xi2qh=#(y1ht<mz1hk2_-BW3zWZQOn&BF-DJNiVJ^UX?IbdyF-0 -zmYg7{z)#}hLcrrTmcVBJ-7O#q)Ue|c4_m)wviwN|OXYK1i@&98_P^=u3fJGVWKtPj -zLs?WVkSk!O^@K;NKZL<c0zjFD)s9i7FY7DW#K^@KP^{b~G3k3kS$~nO@HF(x9_=3o -z>Cb%~Wdvc^;lfge`vp1dg{O^Aqhg$$l5i=+C+Ser`<Wg)9QRGDYvyN4sSVl`6z?{B -z2h<>KQQfEhZr}z4>;>#SGZZ*qGHd~H-az)BPnlSx{cgt);r6Mgt;@-+9-E2t@FXz( -zkh$)!g3>JMRK2Fj;(t$e?z7fJ;>m@#_j;z{x_|Hzf&NnB2s)A$gs4~;$GCPhUTy3P -z%V#3D9@E1QNOb5UL}Ny_3_nU3V+}u&a}K`l<S=I_q0bw!SVz^BZHUO(TE4MzZG&hv -z)+F*X8}QBDV_CEe<6f<02^%m7*+MEwvjSRh#odK&cU%lpy?^`{7NcR^sU%E*+(Vq| -zF~fBmxj2s}!*-mJ%K;2$0V^tq99=5EopA;?6BncK8H3Nu^jJ;;Kab!7;sYgKSZ@Gt -zKv8=%d_ID#m7X)W2w?-i6t|7q0>A2AVv-@33!d)C9C2b%Dl#4Wp`G3Y#VXS2vODOK -zH6Ik?Qx|Shj(@mOGi-V8X@6z3u=_{}wqW)r%+?8?joDa^!2`v;{CIT;J4sydrLxNW -zgUBvqK&gHOJyAP#hP2e3p;XKF@8~4;2})IVed0tk&>;1X$v5<9B1$g>xX)iE=u<cm -zo?`eC3Yy%Ey0VMh!y;fRqb!;mk=8A@RDT10v?wO&6Mu~_WsIoxKM+xi---tWuims! -zj=~aAegI;IcBVmAc9q7(=cq;}OnHg8)o<i1`)eG>55Vhuq!Be_Zh7H_L0ojmJ-L7F -zFE;pV4HH_WmO_~*TJ#EHu@A`M)iV-3k0!7^nIQ%08mJA-{<~wkIj0>_AP%Vz_4#<* -vVkRz)@E~<X?BYZ$D8XaYxPKYw=O=*!-kqz(*(SYUmC&YW)6KUO5CQD(E<g{{ - -delta 4145 -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 - diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify_large.src b/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify_large.src Binary files differdeleted file mode 100644 index 90a9f6d..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_delta_modify_large.src +++ /dev/null diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_literal_create.out b/pkg/gitdiff/testdata/apply/bin_fragment_literal_create.out Binary files differdeleted file mode 100644 index c62cba2..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_literal_create.out +++ /dev/null diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_literal_create.patch b/pkg/gitdiff/testdata/apply/bin_fragment_literal_create.patch deleted file mode 100644 index b3b846a..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_literal_create.patch +++ /dev/null @@ -1,8 +0,0 @@ -diff --git a/gitdiff/testdata/apply/bin_fragment_literal_create.src b/gitdiff/testdata/apply/bin_fragment_literal_create.src -GIT binary patch -literal 32 -ocmZQzU`lR_IpTEv<rOIzfy0`|3>L*`JUiBtu5<US@-j_*0M$he#sB~S - -literal 0 -HcmV?d00001 - diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_literal_create.src b/pkg/gitdiff/testdata/apply/bin_fragment_literal_create.src deleted file mode 100644 index e69de29..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_literal_create.src +++ /dev/null diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_literal_modify.out b/pkg/gitdiff/testdata/apply/bin_fragment_literal_modify.out Binary files differdeleted file mode 100644 index 0bf736e..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_literal_modify.out +++ /dev/null diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_literal_modify.patch b/pkg/gitdiff/testdata/apply/bin_fragment_literal_modify.patch deleted file mode 100644 index c3da024..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_literal_modify.patch +++ /dev/null @@ -1,8 +0,0 @@ -diff --git a/gitdiff/testdata/apply/bin_fragment_literal_modify.src b/gitdiff/testdata/apply/bin_fragment_literal_modify.src -GIT binary patch -literal 32 -ocmZQzU`lR_IpTEv<rOIzfy0_p?@r&O@$6Vny3XCR%F8tM0pJ`CjQ{`u - -literal 32 -ocmZQzU`lR_IpTEv<rOIzfy0`|3>L*`JUiBtu5<US@-j_*0M$he#sB~S - diff --git a/pkg/gitdiff/testdata/apply/bin_fragment_literal_modify.src b/pkg/gitdiff/testdata/apply/bin_fragment_literal_modify.src Binary files differdeleted file mode 100644 index c62cba2..0000000 --- a/pkg/gitdiff/testdata/apply/bin_fragment_literal_modify.src +++ /dev/null diff --git a/pkg/gitdiff/testdata/apply/file_bin_modify.out b/pkg/gitdiff/testdata/apply/file_bin_modify.out Binary files differdeleted file mode 100644 index f3386d1..0000000 --- a/pkg/gitdiff/testdata/apply/file_bin_modify.out +++ /dev/null diff --git a/pkg/gitdiff/testdata/apply/file_bin_modify.patch b/pkg/gitdiff/testdata/apply/file_bin_modify.patch deleted file mode 100644 index af38f36..0000000 --- a/pkg/gitdiff/testdata/apply/file_bin_modify.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/gitdiff/testdata/apply/file_bin_modify.src b/gitdiff/testdata/apply/file_bin_modify.src -GIT binary patch -delta 172 -zcmV;d08{^f2)qc8AP{I3VQ>J`s>wb0HU+h#6w8q?tUO~cHmDjZi2<8yZ9XmKhhMdo -zWu(4bg|8QwzZ|1e*rL4P#)`Fen<n~ik=E?$qG6?hzJ6$u{l5W#?uwHb0q6w)00000 -zlLZ3%0RfW%1N%UMJ{~Z~0@X${&1Kk#98tb3==a{J7A;`O`v&<T@514_mvMTz72b#n -atf$#NLoPbNe?RPFJVt1aCFGoQbiKD!OHgJ2 - -delta 112 -zcmV-$0FVE?2!IHXAP~DY<7&llQfwqYA%tL<sR@xVtUMD;+4ZG>XTQ5=J2y;^BfB}4 -zWkisH791|vOVl5e-@^VLX0s~Ky_UyN!3;CgPr>Edj0j+0gOSwSsFsr$0q6zUJph<q -SlLZ3%0XmZb1N#I__7UCuR5Dxu - diff --git a/pkg/gitdiff/testdata/apply/file_bin_modify.src b/pkg/gitdiff/testdata/apply/file_bin_modify.src Binary files differdeleted file mode 100644 index fb85478..0000000 --- a/pkg/gitdiff/testdata/apply/file_bin_modify.src +++ /dev/null diff --git a/pkg/gitdiff/testdata/apply/file_mode_change.out b/pkg/gitdiff/testdata/apply/file_mode_change.out deleted file mode 100644 index ec3b7fd..0000000 --- a/pkg/gitdiff/testdata/apply/file_mode_change.out +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -echo "this file is executable" diff --git a/pkg/gitdiff/testdata/apply/file_mode_change.patch b/pkg/gitdiff/testdata/apply/file_mode_change.patch deleted file mode 100644 index b1f6859..0000000 --- a/pkg/gitdiff/testdata/apply/file_mode_change.patch +++ /dev/null @@ -1,3 +0,0 @@ -diff --git a/gitdiff/testdata/apply/file_mode_change.src b/gitdiff/testdata/apply/file_mode_change.src -old mode 100644 -new mode 100755 diff --git a/pkg/gitdiff/testdata/apply/file_mode_change.src b/pkg/gitdiff/testdata/apply/file_mode_change.src deleted file mode 100644 index ec3b7fd..0000000 --- a/pkg/gitdiff/testdata/apply/file_mode_change.src +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -echo "this file is executable" diff --git a/pkg/gitdiff/testdata/apply/file_text.src b/pkg/gitdiff/testdata/apply/file_text.src deleted file mode 100644 index 3805ad4..0000000 --- a/pkg/gitdiff/testdata/apply/file_text.src +++ /dev/null @@ -1,200 +0,0 @@ -this is line 1 -this is line 2 -this is line 3 -this is line 4 -this is line 5 -this is line 6 -this is line 7 -this is line 8 -this is line 9 -this is line 10 -this is line 11 -this is line 12 -this is line 13 -this is line 14 -this is line 15 -this is line 16 -this is line 17 -this is line 18 -this is line 19 -this is line 20 -this is line 21 -this is line 22 -this is line 23 -this is line 24 -this is line 25 -this is line 26 -this is line 27 -this is line 28 -this is line 29 -this is line 30 -this is line 31 -this is line 32 -this is line 33 -this is line 34 -this is line 35 -this is line 36 -this is line 37 -this is line 38 -this is line 39 -this is line 40 -this is line 41 -this is line 42 -this is line 43 -this is line 44 -this is line 45 -this is line 46 -this is line 47 -this is line 48 -this is line 49 -this is line 50 -this is line 51 -this is line 52 -this is line 53 -this is line 54 -this is line 55 -this is line 56 -this is line 57 -this is line 58 -this is line 59 -this is line 60 -this is line 61 -this is line 62 -this is line 63 -this is line 64 -this is line 65 -this is line 66 -this is line 67 -this is line 68 -this is line 69 -this is line 70 -this is line 71 -this is line 72 -this is line 73 -this is line 74 -this is line 75 -this is line 76 -this is line 77 -this is line 78 -this is line 79 -this is line 80 -this is line 81 -this is line 82 -this is line 83 -this is line 84 -this is line 85 -this is line 86 -this is line 87 -this is line 88 -this is line 89 -this is line 90 -this is line 91 -this is line 92 -this is line 93 -this is line 94 -this is line 95 -this is line 96 -this is line 97 -this is line 98 -this is line 99 -this is line 100 -this is line 101 -this is line 102 -this is line 103 -this is line 104 -this is line 105 -this is line 106 -this is line 107 -this is line 108 -this is line 109 -this is line 110 -this is line 111 -this is line 112 -this is line 113 -this is line 114 -this is line 115 -this is line 116 -this is line 117 -this is line 118 -this is line 119 -this is line 120 -this is line 121 -this is line 122 -this is line 123 -this is line 124 -this is line 125 -this is line 126 -this is line 127 -this is line 128 -this is line 129 -this is line 130 -this is line 131 -this is line 132 -this is line 133 -this is line 134 -this is line 135 -this is line 136 -this is line 137 -this is line 138 -this is line 139 -this is line 140 -this is line 141 -this is line 142 -this is line 143 -this is line 144 -this is line 145 -this is line 146 -this is line 147 -this is line 148 -this is line 149 -this is line 150 -this is line 151 -this is line 152 -this is line 153 -this is line 154 -this is line 155 -this is line 156 -this is line 157 -this is line 158 -this is line 159 -this is line 160 -this is line 161 -this is line 162 -this is line 163 -this is line 164 -this is line 165 -this is line 166 -this is line 167 -this is line 168 -this is line 169 -this is line 170 -this is line 171 -this is line 172 -this is line 173 -this is line 174 -this is line 175 -this is line 176 -this is line 177 -this is line 178 -this is line 179 -this is line 180 -this is line 181 -this is line 182 -this is line 183 -this is line 184 -this is line 185 -this is line 186 -this is line 187 -this is line 188 -this is line 189 -this is line 190 -this is line 191 -this is line 192 -this is line 193 -this is line 194 -this is line 195 -this is line 196 -this is line 197 -this is line 198 -this is line 199 -this is line 200 diff --git a/pkg/gitdiff/testdata/apply/file_text_delete.out b/pkg/gitdiff/testdata/apply/file_text_delete.out deleted file mode 100644 index e69de29..0000000 --- a/pkg/gitdiff/testdata/apply/file_text_delete.out +++ /dev/null diff --git a/pkg/gitdiff/testdata/apply/file_text_delete.patch b/pkg/gitdiff/testdata/apply/file_text_delete.patch deleted file mode 100644 index 9ac710b..0000000 --- a/pkg/gitdiff/testdata/apply/file_text_delete.patch +++ /dev/null @@ -1,206 +0,0 @@ -diff --git a/gitdiff/testdata/apply/file_text.src.src b/gitdiff/testdata/apply/file_text.src -deleted file mode 100644 -index 3805ad4..0000000 ---- a/gitdiff/testdata/apply/file_text.src.src -+++ /dev/null -@@ -1,200 +0,0 @@ --this is line 1 --this is line 2 --this is line 3 --this is line 4 --this is line 5 --this is line 6 --this is line 7 --this is line 8 --this is line 9 --this is line 10 --this is line 11 --this is line 12 --this is line 13 --this is line 14 --this is line 15 --this is line 16 --this is line 17 --this is line 18 --this is line 19 --this is line 20 --this is line 21 --this is line 22 --this is line 23 --this is line 24 --this is line 25 --this is line 26 --this is line 27 --this is line 28 --this is line 29 --this is line 30 --this is line 31 --this is line 32 --this is line 33 --this is line 34 --this is line 35 --this is line 36 --this is line 37 --this is line 38 --this is line 39 --this is line 40 --this is line 41 --this is line 42 --this is line 43 --this is line 44 --this is line 45 --this is line 46 --this is line 47 --this is line 48 --this is line 49 --this is line 50 --this is line 51 --this is line 52 --this is line 53 --this is line 54 --this is line 55 --this is line 56 --this is line 57 --this is line 58 --this is line 59 --this is line 60 --this is line 61 --this is line 62 --this is line 63 --this is line 64 --this is line 65 --this is line 66 --this is line 67 --this is line 68 --this is line 69 --this is line 70 --this is line 71 --this is line 72 --this is line 73 --this is line 74 --this is line 75 --this is line 76 --this is line 77 --this is line 78 --this is line 79 --this is line 80 --this is line 81 --this is line 82 --this is line 83 --this is line 84 --this is line 85 --this is line 86 --this is line 87 --this is line 88 --this is line 89 --this is line 90 --this is line 91 --this is line 92 --this is line 93 --this is line 94 --this is line 95 --this is line 96 --this is line 97 --this is line 98 --this is line 99 --this is line 100 --this is line 101 --this is line 102 --this is line 103 --this is line 104 --this is line 105 --this is line 106 --this is line 107 --this is line 108 --this is line 109 --this is line 110 --this is line 111 --this is line 112 --this is line 113 --this is line 114 --this is line 115 --this is line 116 --this is line 117 --this is line 118 --this is line 119 --this is line 120 --this is line 121 --this is line 122 --this is line 123 --this is line 124 --this is line 125 --this is line 126 --this is line 127 --this is line 128 --this is line 129 --this is line 130 --this is line 131 --this is line 132 --this is line 133 --this is line 134 --this is line 135 --this is line 136 --this is line 137 --this is line 138 --this is line 139 --this is line 140 --this is line 141 --this is line 142 --this is line 143 --this is line 144 --this is line 145 --this is line 146 --this is line 147 --this is line 148 --this is line 149 --this is line 150 --this is line 151 --this is line 152 --this is line 153 --this is line 154 --this is line 155 --this is line 156 --this is line 157 --this is line 158 --this is line 159 --this is line 160 --this is line 161 --this is line 162 --this is line 163 --this is line 164 --this is line 165 --this is line 166 --this is line 167 --this is line 168 --this is line 169 --this is line 170 --this is line 171 --this is line 172 --this is line 173 --this is line 174 --this is line 175 --this is line 176 --this is line 177 --this is line 178 --this is line 179 --this is line 180 --this is line 181 --this is line 182 --this is line 183 --this is line 184 --this is line 185 --this is line 186 --this is line 187 --this is line 188 --this is line 189 --this is line 190 --this is line 191 --this is line 192 --this is line 193 --this is line 194 --this is line 195 --this is line 196 --this is line 197 --this is line 198 --this is line 199 --this is line 200 diff --git a/pkg/gitdiff/testdata/apply/file_text_error_partial_delete.patch b/pkg/gitdiff/testdata/apply/file_text_error_partial_delete.patch deleted file mode 100644 index 01d2a6f..0000000 --- a/pkg/gitdiff/testdata/apply/file_text_error_partial_delete.patch +++ /dev/null @@ -1,106 +0,0 @@ -diff --git a/gitdiff/testdata/apply/file_text.src.src b/gitdiff/testdata/apply/file_text.src -deleted file mode 100644 -index 3805ad4..0000000 ---- a/gitdiff/testdata/apply/file_text.src.src -+++ /dev/null -@@ -1,100 +0,0 @@ --this is line 1 --this is line 2 --this is line 3 --this is line 4 --this is line 5 --this is line 6 --this is line 7 --this is line 8 --this is line 9 --this is line 10 --this is line 11 --this is line 12 --this is line 13 --this is line 14 --this is line 15 --this is line 16 --this is line 17 --this is line 18 --this is line 19 --this is line 20 --this is line 21 --this is line 22 --this is line 23 --this is line 24 --this is line 25 --this is line 26 --this is line 27 --this is line 28 --this is line 29 --this is line 30 --this is line 31 --this is line 32 --this is line 33 --this is line 34 --this is line 35 --this is line 36 --this is line 37 --this is line 38 --this is line 39 --this is line 40 --this is line 41 --this is line 42 --this is line 43 --this is line 44 --this is line 45 --this is line 46 --this is line 47 --this is line 48 --this is line 49 --this is line 50 --this is line 51 --this is line 52 --this is line 53 --this is line 54 --this is line 55 --this is line 56 --this is line 57 --this is line 58 --this is line 59 --this is line 60 --this is line 61 --this is line 62 --this is line 63 --this is line 64 --this is line 65 --this is line 66 --this is line 67 --this is line 68 --this is line 69 --this is line 70 --this is line 71 --this is line 72 --this is line 73 --this is line 74 --this is line 75 --this is line 76 --this is line 77 --this is line 78 --this is line 79 --this is line 80 --this is line 81 --this is line 82 --this is line 83 --this is line 84 --this is line 85 --this is line 86 --this is line 87 --this is line 88 --this is line 89 --this is line 90 --this is line 91 --this is line 92 --this is line 93 --this is line 94 --this is line 95 --this is line 96 --this is line 97 --this is line 98 --this is line 99 --this is line 100 diff --git a/pkg/gitdiff/testdata/apply/file_text_modify.out b/pkg/gitdiff/testdata/apply/file_text_modify.out deleted file mode 100644 index dc20c07..0000000 --- a/pkg/gitdiff/testdata/apply/file_text_modify.out +++ /dev/null @@ -1,195 +0,0 @@ -the first line is different -this is line 2 -this is line 3 -this is line 4 -this is line 5 -this is line 6 -this is line 7 -this is line 8 -this is line 9 -this is line 10 -this is line 11 -this is line 12 -this is line 13 -this is line 14 -this is line 15 -this is line 16 -this is line 17 -this is line 18 -this is line 19 -this line offsets all the line numbers! -this is line 20 -this is line 21 -until here, now we're back on track! -this is line 24 -this is line 25 -this is line 26 -this is line 27 -this is line 28 -this is line 29 -this is line 30 -this is line 31 -this is line 32 -this is line 33 -this is line 34 -this is line 35 -this is line 36 -this is line 37 -this is line 38 -this is line 39 -this is line 40 -this is line 41 -this is line 42 -this is line 43 -this is line 44 -this is line 45 -this is line 46 -this is line 47 -this is line 48 -this is line 49 -this is line 50 -this is line 51 -this is line 52 -this is line 53 -this is line 54 -this is line 55 -once upon a time, a line - in a text - file - changed -this is line 60 -this is line 61 -this is line 62 -this is line 63 -this is line 64 -this is line 65 -this is line 66 -this is line 67 -this is line 68 -this is line 69 -this is line 70 -this is line 71 -this is line 72 -this is line 73 -this is line 74 -this is line 75 -this is line 76 -this is line 77 -this is line 78 -this is line 79 -this is line 80 -this is line 81 -this is line 82 -this is line 83 -this is line 84 -this is line 85 -this is line 86 -this is line 87 -this is line 88 -this is line 89 -this is line 90 -this is line 91 -this is line 92 -this is line 93 -this is line 94 -this is line 95 -this is line 96 -this is line 97 -this is line 98 -this is line 99 -this is line 100 -this is line 101 -this is line 102 -this is line 103 -this is line 104 -this is line 105 -this is line 106 -this is line 107 -this is line 108 -this is line 109 -this is line 110 -this is line 111 -this is line 112 -this is line 113 -this is line 114 -this is line 115 -this is line 116 -this is line 117 -this is line 118 -this is line 119 -this is line 120 -this is line 121 -this is line 122 -this is line 123 -this is line 124 -this is line 125 -this is line 126 -this is line 127 -this is line 128 -this is line 129 -this is line 130 -this is line 131 -this is line 132 -this line was bad and has been removed -this line was REDACTED and has been REDACTED -this is line 135 -this is line 136 -this is line 137 -this is line 138 -this is line 139 -this is line 140 -this is line 141 -this is line 142 -this is line 143 -this is line 144 -this is line 145 -this is line 146 -this is line 147 -this is line 148 -this is line 149 -this is line 150 -this is line 151 -this is line 152 -this is line 153 -this is line 154 -this is line 155 -this is line 156 -this is line 157 -this is line 158 -this is line 159 -this is line 160 -this is line 161 -this is line 162 -this is line 163 -the number on the remaining lines is 5 ahead of their actual position in the file -this is line 170 -this is line 171 -this is line 172 -this is line 173 -this is line 174 -this is line 175 -this is line 176 -this is line 177 -this is line 178 -this is line 179 -this is line 180 -this is line 181 -this is line 182 -this is line 183 -this is line 184 -this is line 185 -this is line 186 -this is line 187 -this is line 188 -this is line 189 -this is line 190 -this is line 191 -this is line 192 -this is line 193 -this is line 194 -this is line 195 -this is line 196 -this is line 197 -this is line 198 -this is line 199 -this is line 200 diff --git a/pkg/gitdiff/testdata/apply/file_text_modify.patch b/pkg/gitdiff/testdata/apply/file_text_modify.patch deleted file mode 100644 index 362d9a9..0000000 --- a/pkg/gitdiff/testdata/apply/file_text_modify.patch +++ /dev/null @@ -1,62 +0,0 @@ -diff --git a/gitdiff/testdata/apply/file_text.src b/gitdiff/testdata/apply/file_text.src ---- a/gitdiff/testdata/apply/file_text.src -+++ b/gitdiff/testdata/apply/file_text.src -@@ -1,4 +1,4 @@ --this is line 1 -+the first line is different - this is line 2 - this is line 3 - this is line 4 -@@ -17,10 +17,10 @@ this is line 16 - this is line 17 - this is line 18 - this is line 19 -+this line offsets all the line numbers! - this is line 20 - this is line 21 --this is line 22 --this is line 23 -+until here, now we're back on track! - this is line 24 - this is line 25 - this is line 26 -@@ -53,10 +53,10 @@ this is line 52 - this is line 53 - this is line 54 - this is line 55 --this is line 56 --this is line 57 --this is line 58 --this is line 59 -+once upon a time, a line -+ in a text -+ file -+ changed - this is line 60 - this is line 61 - this is line 62 -@@ -130,8 +130,8 @@ this is line 129 - this is line 130 - this is line 131 - this is line 132 --this is line 133 --this is line 134 -+this line was bad and has been removed -+this line was REDACTED and has been REDACTED - this is line 135 - this is line 136 - this is line 137 -@@ -161,12 +161,7 @@ this is line 160 - this is line 161 - this is line 162 - this is line 163 --this is line 164 --this is line 165 --this is line 166 --this is line 167 --this is line 168 --this is line 169 -+the number on the remaining lines is 5 ahead of their actual position in the file - this is line 170 - this is line 171 - this is line 172 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_add_end.out b/pkg/gitdiff/testdata/apply/text_fragment_add_end.out deleted file mode 100644 index 648fd44..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_add_end.out +++ /dev/null @@ -1,5 +0,0 @@ -line 1 -line 2 -line 3 -new line a -new line b diff --git a/pkg/gitdiff/testdata/apply/text_fragment_add_end.patch b/pkg/gitdiff/testdata/apply/text_fragment_add_end.patch deleted file mode 100644 index de708be..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_add_end.patch +++ /dev/null @@ -1,9 +0,0 @@ -diff --git a/gitdiff/testdata/apply/fragment_add_end.src b/gitdiff/testdata/apply/fragment_add_end.src ---- a/gitdiff/testdata/apply/fragment_add_end.src -+++ b/gitdiff/testdata/apply/fragment_add_end.src -@@ -1,3 +1,5 @@ - line 1 - line 2 - line 3 -+new line a -+new line b diff --git a/pkg/gitdiff/testdata/apply/text_fragment_add_end.src b/pkg/gitdiff/testdata/apply/text_fragment_add_end.src deleted file mode 100644 index a92d664..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_add_end.src +++ /dev/null @@ -1,3 +0,0 @@ -line 1 -line 2 -line 3 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_add_end_noeol.out b/pkg/gitdiff/testdata/apply/text_fragment_add_end_noeol.out deleted file mode 100644 index 94c99a3..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_add_end_noeol.out +++ /dev/null @@ -1,5 +0,0 @@ -line 1 -line 2 -line 3 -line 4 -line 5 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_add_end_noeol.patch b/pkg/gitdiff/testdata/apply/text_fragment_add_end_noeol.patch deleted file mode 100644 index ec3cea4..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_add_end_noeol.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff --git a/gitdiff/testdata/apply/text_fragment_add_end_noeol.src b/gitdiff/testdata/apply/text_fragment_add_end_noeol.src ---- a/gitdiff/testdata/apply/text_fragment_add_end_noeol.src -+++ b/gitdiff/testdata/apply/text_fragment_add_end_noeol.src -@@ -1,3 +1,5 @@ - line 1 - line 2 --line 3 -\ No newline at end of file -+line 3 -+line 4 -+line 5 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_add_end_noeol.src b/pkg/gitdiff/testdata/apply/text_fragment_add_end_noeol.src deleted file mode 100644 index 8cf2f17..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_add_end_noeol.src +++ /dev/null @@ -1,3 +0,0 @@ -line 1 -line 2 -line 3
\ No newline at end of file diff --git a/pkg/gitdiff/testdata/apply/text_fragment_add_middle.out b/pkg/gitdiff/testdata/apply/text_fragment_add_middle.out deleted file mode 100644 index ded20d8..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_add_middle.out +++ /dev/null @@ -1,5 +0,0 @@ -line 1 -line 2 -new line a -new line b -line 3 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_add_middle.patch b/pkg/gitdiff/testdata/apply/text_fragment_add_middle.patch deleted file mode 100644 index 43aee3b..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_add_middle.patch +++ /dev/null @@ -1,9 +0,0 @@ -diff --git a/gitdiff/testdata/apply/fragment_add_middle.src b/gitdiff/testdata/apply/fragment_add_middle.src ---- a/gitdiff/testdata/apply/fragment_add_middle.src -+++ b/gitdiff/testdata/apply/fragment_add_middle.src -@@ -1,3 +1,5 @@ - line 1 - line 2 -+new line a -+new line b - line 3 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_add_middle.src b/pkg/gitdiff/testdata/apply/text_fragment_add_middle.src deleted file mode 100644 index a92d664..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_add_middle.src +++ /dev/null @@ -1,3 +0,0 @@ -line 1 -line 2 -line 3 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_add_start.out b/pkg/gitdiff/testdata/apply/text_fragment_add_start.out deleted file mode 100644 index b153f60..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_add_start.out +++ /dev/null @@ -1,4 +0,0 @@ -new line a -line 1 -line 2 -line 3 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_add_start.patch b/pkg/gitdiff/testdata/apply/text_fragment_add_start.patch deleted file mode 100644 index 5218764..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_add_start.patch +++ /dev/null @@ -1,8 +0,0 @@ -diff --git a/gitdiff/testdata/apply/fragment_add_start.src b/gitdiff/testdata/apply/fragment_add_start.src ---- a/gitdiff/testdata/apply/fragment_add_start.src -+++ b/gitdiff/testdata/apply/fragment_add_start.src -@@ -1,3 +1,4 @@ -+new line a - line 1 - line 2 - line 3 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_add_start.src b/pkg/gitdiff/testdata/apply/text_fragment_add_start.src deleted file mode 100644 index a92d664..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_add_start.src +++ /dev/null @@ -1,3 +0,0 @@ -line 1 -line 2 -line 3 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_end.out b/pkg/gitdiff/testdata/apply/text_fragment_change_end.out deleted file mode 100644 index e3cbece..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_end.out +++ /dev/null @@ -1,10 +0,0 @@ -line 1 -line 2 -line 3 -line 4 -line 5 -line 6 -line 7 -line 8 -line 9 -new line a diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_end.patch b/pkg/gitdiff/testdata/apply/text_fragment_change_end.patch deleted file mode 100644 index 5655880..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_end.patch +++ /dev/null @@ -1,9 +0,0 @@ -diff --git a/gitdiff/testdata/apply/text_fragment_change_end.src b/gitdiff/testdata/apply/text_fragment_change_end.src ---- a/gitdiff/testdata/apply/text_fragment_change_end.src -+++ b/gitdiff/testdata/apply/text_fragment_change_end.src -@@ -7,4 +7,4 @@ line 6 - line 7 - line 8 - line 9 --line 10 -+new line a diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_end.src b/pkg/gitdiff/testdata/apply/text_fragment_change_end.src deleted file mode 100644 index fa2da6e..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_end.src +++ /dev/null @@ -1,10 +0,0 @@ -line 1 -line 2 -line 3 -line 4 -line 5 -line 6 -line 7 -line 8 -line 9 -line 10 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_end_eol.out b/pkg/gitdiff/testdata/apply/text_fragment_change_end_eol.out deleted file mode 100644 index 8cf2f17..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_end_eol.out +++ /dev/null @@ -1,3 +0,0 @@ -line 1 -line 2 -line 3
\ No newline at end of file diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_end_eol.patch b/pkg/gitdiff/testdata/apply/text_fragment_change_end_eol.patch deleted file mode 100644 index f1c9477..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_end_eol.patch +++ /dev/null @@ -1,10 +0,0 @@ -diff --git a/gitdiff/testdata/apply/text_fragment_remove_last_eol.src b/gitdiff/testdata/apply/text_fragment_remove_last_eol.src -index a92d664..8cf2f17 100644 ---- a/gitdiff/testdata/apply/text_fragment_remove_last_eol.src -+++ b/gitdiff/testdata/apply/text_fragment_remove_last_eol.src -@@ -1,3 +1,3 @@ - line 1 - line 2 --line 3 -+line 3 -\ No newline at end of file diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_end_eol.src b/pkg/gitdiff/testdata/apply/text_fragment_change_end_eol.src deleted file mode 100644 index a92d664..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_end_eol.src +++ /dev/null @@ -1,3 +0,0 @@ -line 1 -line 2 -line 3 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_exact.out b/pkg/gitdiff/testdata/apply/text_fragment_change_exact.out deleted file mode 100644 index 4655a0a..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_exact.out +++ /dev/null @@ -1,19 +0,0 @@ -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -new line a -line -line -line diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_exact.patch b/pkg/gitdiff/testdata/apply/text_fragment_change_exact.patch deleted file mode 100644 index 395de4d..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_exact.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/gitdiff/testdata/apply/text_fragment_change_exact.src b/gitdiff/testdata/apply/text_fragment_change_exact.src ---- a/gitdiff/testdata/apply/text_fragment_change_exact.src -+++ b/gitdiff/testdata/apply/text_fragment_change_exact.src -@@ -13,7 +13,7 @@ line - line - line - line --line -+new line a - line - line - line diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_exact.src b/pkg/gitdiff/testdata/apply/text_fragment_change_exact.src deleted file mode 100644 index 316a8f0..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_exact.src +++ /dev/null @@ -1,30 +0,0 @@ -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line -line diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_middle.out b/pkg/gitdiff/testdata/apply/text_fragment_change_middle.out deleted file mode 100644 index fd0a9ad..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_middle.out +++ /dev/null @@ -1,9 +0,0 @@ -line 1 -line 2 -line 3 -line 4 -line 5 -new line a -line 7 -line 8 -line 9 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_middle.patch b/pkg/gitdiff/testdata/apply/text_fragment_change_middle.patch deleted file mode 100644 index 139a0fe..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_middle.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/gitdiff/testdata/apply/text_fragment_change_middle.src b/gitdiff/testdata/apply/text_fragment_change_middle.src ---- a/gitdiff/testdata/apply/text_fragment_change_middle.src -+++ b/gitdiff/testdata/apply/text_fragment_change_middle.src -@@ -3,7 +3,7 @@ line 2 - line 3 - line 4 - line 5 --line 6 -+new line a - line 7 - line 8 - line 9 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_middle.src b/pkg/gitdiff/testdata/apply/text_fragment_change_middle.src deleted file mode 100644 index fa2da6e..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_middle.src +++ /dev/null @@ -1,10 +0,0 @@ -line 1 -line 2 -line 3 -line 4 -line 5 -line 6 -line 7 -line 8 -line 9 -line 10 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_single_noeol.out b/pkg/gitdiff/testdata/apply/text_fragment_change_single_noeol.out deleted file mode 100644 index ed59e08..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_single_noeol.out +++ /dev/null @@ -1 +0,0 @@ -new line a
\ No newline at end of file diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_single_noeol.patch b/pkg/gitdiff/testdata/apply/text_fragment_change_single_noeol.patch deleted file mode 100644 index f945234..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_single_noeol.patch +++ /dev/null @@ -1,8 +0,0 @@ -diff --git a/gitdiff/testdata/apply/text_fragment_change_single_noeol.src b/gitdiff/testdata/apply/text_fragment_change_single_noeol.src ---- a/gitdiff/testdata/apply/text_fragment_change_single_noeol.src -+++ b/gitdiff/testdata/apply/text_fragment_change_single_noeol.src -@@ -1 +1 @@ --line 1 -\ No newline at end of file -+new line a -\ No newline at end of file diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_single_noeol.src b/pkg/gitdiff/testdata/apply/text_fragment_change_single_noeol.src deleted file mode 100644 index dcf168c..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_single_noeol.src +++ /dev/null @@ -1 +0,0 @@ -line 1
\ No newline at end of file diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_start.out b/pkg/gitdiff/testdata/apply/text_fragment_change_start.out deleted file mode 100644 index 5156941..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_start.out +++ /dev/null @@ -1,4 +0,0 @@ -new line a -line 2 -line 3 -line 4 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_start.patch b/pkg/gitdiff/testdata/apply/text_fragment_change_start.patch deleted file mode 100644 index d0a6653..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_start.patch +++ /dev/null @@ -1,9 +0,0 @@ -diff --git a/gitdiff/testdata/apply/text_fragment_change_start.src b/gitdiff/testdata/apply/text_fragment_change_start.src ---- a/gitdiff/testdata/apply/text_fragment_change_start.src -+++ b/gitdiff/testdata/apply/text_fragment_change_start.src -@@ -1,4 +1,4 @@ --line 1 -+new line a - line 2 - line 3 - line 4 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_change_start.src b/pkg/gitdiff/testdata/apply/text_fragment_change_start.src deleted file mode 100644 index fa2da6e..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_change_start.src +++ /dev/null @@ -1,10 +0,0 @@ -line 1 -line 2 -line 3 -line 4 -line 5 -line 6 -line 7 -line 8 -line 9 -line 10 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_delete_all.out b/pkg/gitdiff/testdata/apply/text_fragment_delete_all.out deleted file mode 100644 index e69de29..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_delete_all.out +++ /dev/null diff --git a/pkg/gitdiff/testdata/apply/text_fragment_delete_all.patch b/pkg/gitdiff/testdata/apply/text_fragment_delete_all.patch deleted file mode 100644 index 8a2fb9c..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_delete_all.patch +++ /dev/null @@ -1,8 +0,0 @@ -diff --git a/gitdiff/testdata/apply/fragment_delete_all.src b/gitdiff/testdata/apply/fragment_delete_all.src ---- a/gitdiff/testdata/apply/fragment_delete_all.src -+++ b/gitdiff/testdata/apply/fragment_delete_all.src -@@ -1,4 +0,0 @@ --line a --line b --line c --line d diff --git a/pkg/gitdiff/testdata/apply/text_fragment_delete_all.src b/pkg/gitdiff/testdata/apply/text_fragment_delete_all.src deleted file mode 100644 index 47d03ac..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_delete_all.src +++ /dev/null @@ -1,4 +0,0 @@ -line a -line b -line c -line d diff --git a/pkg/gitdiff/testdata/apply/text_fragment_error.src b/pkg/gitdiff/testdata/apply/text_fragment_error.src deleted file mode 100644 index f8b6f0a..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_error.src +++ /dev/null @@ -1,13 +0,0 @@ -line 1 -line 2 -line 3 -line 4 -line 5 -line 6 -line 7 -line 8 -line 9 -line 10 -line 11 -line 12 -line 13 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_error_context_conflict.patch b/pkg/gitdiff/testdata/apply/text_fragment_error_context_conflict.patch deleted file mode 100644 index a262796..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_error_context_conflict.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/gitdiff/testdata/apply/text_fragment_error.src b/gitdiff/testdata/apply/text_fragment_error.src ---- a/gitdiff/testdata/apply/text_fragment_error.src -+++ b/gitdiff/testdata/apply/text_fragment_error.src -@@ -4,7 +4,7 @@ line 3 - line 4 - line 5 - line conflict --line 7 -+new line a - line 8 - line 9 - line 10 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_error_delete_conflict.patch b/pkg/gitdiff/testdata/apply/text_fragment_error_delete_conflict.patch deleted file mode 100644 index 17ea166..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_error_delete_conflict.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/gitdiff/testdata/apply/text_fragment_error.src b/gitdiff/testdata/apply/text_fragment_error.src ---- a/gitdiff/testdata/apply/text_fragment_error.src -+++ b/gitdiff/testdata/apply/text_fragment_error.src -@@ -4,7 +4,7 @@ line 3 - line 4 - line 5 - line 6 --line conflict -+new line a - line 8 - line 9 - line 10 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_error_new_file.patch b/pkg/gitdiff/testdata/apply/text_fragment_error_new_file.patch deleted file mode 100644 index f4fbee6..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_error_new_file.patch +++ /dev/null @@ -1,7 +0,0 @@ -diff --git a/gitdiff/testdata/apply/text_fragment_error.src b/gitdiff/testdata/apply/text_fragment_error.src ---- a/gitdiff/testdata/apply/text_fragment_error.src -+++ b/gitdiff/testdata/apply/text_fragment_error.src -@@ -0,0 +1,3 @@ -+line 1 -+line 2 -+line 3 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_error_short_src.patch b/pkg/gitdiff/testdata/apply/text_fragment_error_short_src.patch deleted file mode 100644 index bfe7b96..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_error_short_src.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/gitdiff/testdata/apply/text_fragment_error.src b/gitdiff/testdata/apply/text_fragment_error.src ---- a/gitdiff/testdata/apply/text_fragment_error.src -+++ b/gitdiff/testdata/apply/text_fragment_error.src -@@ -9,7 +9,7 @@ line 8 - line 9 - line 10 - line 11 --line 12 -+new line a - line 13 - line 14 - line 15 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_error_short_src_before.patch b/pkg/gitdiff/testdata/apply/text_fragment_error_short_src_before.patch deleted file mode 100644 index 0a96018..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_error_short_src_before.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/gitdiff/testdata/apply/text_fragment_error.src b/gitdiff/testdata/apply/text_fragment_error.src ---- a/gitdiff/testdata/apply/text_fragment_error.src -+++ b/gitdiff/testdata/apply/text_fragment_error.src -@@ -15,7 +15,7 @@ line 14 - line 15 - line 16 - line 17 --line 18 -+new line a - line 19 - line 20 - line 21 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_new.out b/pkg/gitdiff/testdata/apply/text_fragment_new.out deleted file mode 100644 index a92d664..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_new.out +++ /dev/null @@ -1,3 +0,0 @@ -line 1 -line 2 -line 3 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_new.patch b/pkg/gitdiff/testdata/apply/text_fragment_new.patch deleted file mode 100644 index c87487b..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_new.patch +++ /dev/null @@ -1,7 +0,0 @@ -diff --git a/gitdiff/testdata/apply/fragment_new.src b/gitdiff/testdata/apply/fragment_new.src ---- a/gitdiff/testdata/apply/fragment_new.src -+++ b/gitdiff/testdata/apply/fragment_new.src -@@ -0,0 +1,3 @@ -+line 1 -+line 2 -+line 3 diff --git a/pkg/gitdiff/testdata/apply/text_fragment_new.src b/pkg/gitdiff/testdata/apply/text_fragment_new.src deleted file mode 100644 index e69de29..0000000 --- a/pkg/gitdiff/testdata/apply/text_fragment_new.src +++ /dev/null diff --git a/pkg/gitdiff/testdata/new_binary_file.patch b/pkg/gitdiff/testdata/new_binary_file.patch deleted file mode 100644 index e9ad45d..0000000 --- a/pkg/gitdiff/testdata/new_binary_file.patch +++ /dev/null @@ -1,16 +0,0 @@ -commit 5d9790fec7d95aa223f3d20936340bf55ff3dcbe -Author: Morton Haypenny <mhaypenny@example.com> -Date: Tue Apr 2 22:55:40 2019 -0700 - - A binary file with the first 10 fibonacci numbers. - -diff --git a/dir/ten.bin b/dir/ten.bin -new file mode 100644 -index 0000000000000000000000000000000000000000..77b068ba48c356156944ea714740d0d5ca07bfec -GIT binary patch -literal 40 -gcmZQzU|?i`U?w2V48*KJ%mKu_Kr9NxN<eH500b)lkN^Mx - -literal 0 -HcmV?d00001 - diff --git a/pkg/gitdiff/testdata/no_files.patch b/pkg/gitdiff/testdata/no_files.patch deleted file mode 100644 index 9eea12d..0000000 --- a/pkg/gitdiff/testdata/no_files.patch +++ /dev/null @@ -1,8 +0,0 @@ -commit 5d9790fec7d95aa223f3d20936340bf55ff3dcbe -Author: Morton Haypenny <mhaypenny@example.com> -Date: Tue Apr 2 22:55:40 2019 -0700 - - A file with multiple fragments. - - The content is arbitrary. - diff --git a/pkg/gitdiff/testdata/one_file.patch b/pkg/gitdiff/testdata/one_file.patch deleted file mode 100644 index 1aefec3..0000000 --- a/pkg/gitdiff/testdata/one_file.patch +++ /dev/null @@ -1,28 +0,0 @@ -commit 5d9790fec7d95aa223f3d20936340bf55ff3dcbe -Author: Morton Haypenny <mhaypenny@example.com> -Date: Tue Apr 2 22:55:40 2019 -0700 - - A file with multiple fragments. - - The content is arbitrary. - -diff --git a/dir/file1.txt b/dir/file1.txt -index ebe9fa54..fe103e1d 100644 ---- a/dir/file1.txt -+++ b/dir/file1.txt -@@ -3,6 +3,8 @@ fragment 1 - context line --old line 1 --old line 2 - context line -+new line 1 -+new line 2 -+new line 3 - context line --old line 3 -+new line 4 -+new line 5 -@@ -31,2 +33,2 @@ fragment 2 - context line --old line 4 -+new line 6 diff --git a/pkg/gitdiff/testdata/string/binary_modify.patch b/pkg/gitdiff/testdata/string/binary_modify.patch deleted file mode 100644 index 12ddad5..0000000 --- a/pkg/gitdiff/testdata/string/binary_modify.patch +++ /dev/null @@ -1,9 +0,0 @@ -diff --git a/file.bin b/file.bin -index a7f4d5d6975ec021016c02b6d58345ebf434f38c..bdc9a70f055892146612dcdb413f0e339faaa0df 100644 -GIT binary patch -delta 66 -QcmeZhVVvM$!$1K50C&Ox;s5{u - -delta 5 -McmZo+^qAlQ00i9urT_o{ - diff --git a/pkg/gitdiff/testdata/string/binary_modify_nodata.patch b/pkg/gitdiff/testdata/string/binary_modify_nodata.patch deleted file mode 100644 index 833a534..0000000 --- a/pkg/gitdiff/testdata/string/binary_modify_nodata.patch +++ /dev/null @@ -1,3 +0,0 @@ -diff --git a/file.bin b/file.bin -index a7f4d5d..bdc9a70 100644 -Binary files a/file.bin and b/file.bin differ diff --git a/pkg/gitdiff/testdata/string/binary_new.patch b/pkg/gitdiff/testdata/string/binary_new.patch deleted file mode 100644 index c56f35e..0000000 --- a/pkg/gitdiff/testdata/string/binary_new.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff --git a/file.bin b/file.bin -new file mode 100644 -index 0000000000000000000000000000000000000000..a7f4d5d6975ec021016c02b6d58345ebf434f38c -GIT binary patch -literal 72 -zcmV-O0Jr~td-`u6JcK&{KDK=<a#;v1^LR5&K)zQ0=Goz82(?nJ6_nD`f#8O9p}}{P -eiXim+rDI+BDadMQmMsO5Sw@;DbrCA+PamP;Ng_@F - -literal 0 -HcmV?d00001 - diff --git a/pkg/gitdiff/testdata/string/copy.patch b/pkg/gitdiff/testdata/string/copy.patch deleted file mode 100644 index f002f07..0000000 --- a/pkg/gitdiff/testdata/string/copy.patch +++ /dev/null @@ -1,4 +0,0 @@ -diff --git a/file.txt b/numbers.txt -similarity index 100% -copy from file.txt -copy to numbers.txt diff --git a/pkg/gitdiff/testdata/string/copy_modify.patch b/pkg/gitdiff/testdata/string/copy_modify.patch deleted file mode 100644 index 558a511..0000000 --- a/pkg/gitdiff/testdata/string/copy_modify.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/file.txt b/numbers.txt -similarity index 57% -copy from file.txt -copy to numbers.txt -index c9e9e05..6c4a3e0 100644 ---- a/file.txt -+++ b/numbers.txt -@@ -1,6 +1,6 @@ - one - two --three -+three three three - four - five - six -@@ -8,3 +8,5 @@ seven - eight - nine - ten -+eleven -+twelve diff --git a/pkg/gitdiff/testdata/string/delete.patch b/pkg/gitdiff/testdata/string/delete.patch deleted file mode 100644 index f32dc25..0000000 --- a/pkg/gitdiff/testdata/string/delete.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/file.txt b/file.txt -deleted file mode 100644 -index c9e9e05..0000000 ---- a/file.txt -+++ /dev/null -@@ -1,10 +0,0 @@ --one --two --three --four --five --six --seven --eight --nine --ten diff --git a/pkg/gitdiff/testdata/string/mode.patch b/pkg/gitdiff/testdata/string/mode.patch deleted file mode 100644 index 953ab25..0000000 --- a/pkg/gitdiff/testdata/string/mode.patch +++ /dev/null @@ -1,3 +0,0 @@ -diff --git a/file.txt b/file.txt -old mode 100644 -new mode 100755 diff --git a/pkg/gitdiff/testdata/string/mode_modify.patch b/pkg/gitdiff/testdata/string/mode_modify.patch deleted file mode 100644 index f1554a7..0000000 --- a/pkg/gitdiff/testdata/string/mode_modify.patch +++ /dev/null @@ -1,10 +0,0 @@ -diff --git a/script.sh b/script.sh -old mode 100644 -new mode 100755 -index 7a870bd..68d501e ---- a/script.sh -+++ b/script.sh -@@ -1,2 +1,2 @@ - #!/bin/bash --echo "Hello World" -+echo "Hello, World!" diff --git a/pkg/gitdiff/testdata/string/modify.patch b/pkg/gitdiff/testdata/string/modify.patch deleted file mode 100644 index 9d89753..0000000 --- a/pkg/gitdiff/testdata/string/modify.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/file.txt b/file.txt -index c9e9e05..7d5fdc6 100644 ---- a/file.txt -+++ b/file.txt -@@ -3,8 +3,10 @@ two - three - four - five --six -+six six six six six six - seven - eight - nine - ten -+eleven -+twelve diff --git a/pkg/gitdiff/testdata/string/new.patch b/pkg/gitdiff/testdata/string/new.patch deleted file mode 100644 index 941fe25..0000000 --- a/pkg/gitdiff/testdata/string/new.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/file.txt b/file.txt -new file mode 100644 -index 0000000..c9e9e05 ---- /dev/null -+++ b/file.txt -@@ -0,0 +1,10 @@ -+one -+two -+three -+four -+five -+six -+seven -+eight -+nine -+ten diff --git a/pkg/gitdiff/testdata/string/new_empty.patch b/pkg/gitdiff/testdata/string/new_empty.patch deleted file mode 100644 index 5cc7cf7..0000000 --- a/pkg/gitdiff/testdata/string/new_empty.patch +++ /dev/null @@ -1,3 +0,0 @@ -diff --git a/file.txt b/file.txt -new file mode 100644 -index 0000000..e69de29 diff --git a/pkg/gitdiff/testdata/string/new_mode.patch b/pkg/gitdiff/testdata/string/new_mode.patch deleted file mode 100644 index f9d7f1f..0000000 --- a/pkg/gitdiff/testdata/string/new_mode.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/file.sh b/file.sh -new file mode 100755 -index 0000000..c9e9e05 ---- /dev/null -+++ b/file.sh -@@ -0,0 +1,10 @@ -+one -+two -+three -+four -+five -+six -+seven -+eight -+nine -+ten diff --git a/pkg/gitdiff/testdata/string/rename.patch b/pkg/gitdiff/testdata/string/rename.patch deleted file mode 100644 index 3c0ca6f..0000000 --- a/pkg/gitdiff/testdata/string/rename.patch +++ /dev/null @@ -1,4 +0,0 @@ -diff --git a/file.txt b/numbers.txt -similarity index 100% -rename from file.txt -rename to numbers.txt diff --git a/pkg/gitdiff/testdata/string/rename_modify.patch b/pkg/gitdiff/testdata/string/rename_modify.patch deleted file mode 100644 index 52a32af..0000000 --- a/pkg/gitdiff/testdata/string/rename_modify.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff --git a/file.txt b/numbers.txt -similarity index 77% -rename from file.txt -rename to numbers.txt -index c9e9e05..a6b31d6 100644 ---- a/file.txt -+++ b/numbers.txt -@@ -3,8 +3,9 @@ two - three - four - five --six -+ six - seven - eight - nine - ten -+eleven diff --git a/pkg/gitdiff/testdata/two_files.patch b/pkg/gitdiff/testdata/two_files.patch deleted file mode 100644 index dd14421..0000000 --- a/pkg/gitdiff/testdata/two_files.patch +++ /dev/null @@ -1,48 +0,0 @@ -commit 5d9790fec7d95aa223f3d20936340bf55ff3dcbe -Author: Morton Haypenny <mhaypenny@example.com> -Date: Tue Apr 2 22:55:40 2019 -0700 - - A file with multiple fragments. - - The content is arbitrary. - -diff --git a/dir/file1.txt b/dir/file1.txt -index ebe9fa54..fe103e1d 100644 ---- a/dir/file1.txt -+++ b/dir/file1.txt -@@ -3,6 +3,8 @@ fragment 1 - context line --old line 1 --old line 2 - context line -+new line 1 -+new line 2 -+new line 3 - context line --old line 3 -+new line 4 -+new line 5 -@@ -31,2 +33,2 @@ fragment 2 - context line --old line 4 -+new line 6 -diff --git a/dir/file2.txt b/dir/file2.txt -index 417ebc70..67514b7f 100644 ---- a/dir/file2.txt -+++ b/dir/file2.txt -@@ -3,6 +3,8 @@ fragment 1 - context line --old line 1 --old line 2 - context line -+new line 1 -+new line 2 -+new line 3 - context line --old line 3 -+new line 4 -+new line 5 -@@ -31,2 +33,2 @@ fragment 2 - context line --old line 4 -+new line 6 diff --git a/pkg/gitdiff/text_test.go b/pkg/gitdiff/text_test.go deleted file mode 100644 index 990b3bc..0000000 --- a/pkg/gitdiff/text_test.go +++ /dev/null @@ -1,488 +0,0 @@ -package gitdiff - -import ( - "io" - "reflect" - "testing" -) - -func TestParseTextFragmentHeader(t *testing.T) { - tests := map[string]struct { - Input string - Output *TextFragment - Err bool - }{ - "shortest": { - Input: "@@ -1 +1 @@\n", - Output: &TextFragment{ - OldPosition: 1, - OldLines: 1, - NewPosition: 1, - NewLines: 1, - }, - }, - "standard": { - Input: "@@ -21,5 +28,9 @@\n", - Output: &TextFragment{ - OldPosition: 21, - OldLines: 5, - NewPosition: 28, - NewLines: 9, - }, - }, - "trailingComment": { - Input: "@@ -21,5 +28,9 @@ func test(n int) {\n", - Output: &TextFragment{ - Comment: "func test(n int) {", - OldPosition: 21, - OldLines: 5, - NewPosition: 28, - NewLines: 9, - }, - }, - "incomplete": { - Input: "@@ -12,3 +2\n", - Err: true, - }, - "badNumbers": { - Input: "@@ -1a,2b +3c,4d @@\n", - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - frag, err := p.ParseTextFragmentHeader() - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing header, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("error parsing header: %v", err) - } - - if !reflect.DeepEqual(test.Output, frag) { - t.Errorf("incorrect fragment\nexpected: %+v\nactual: %+v", test.Output, frag) - } - }) - } -} - -func TestParseTextChunk(t *testing.T) { - tests := map[string]struct { - Input string - Fragment TextFragment - - Output *TextFragment - Err bool - }{ - "addWithContext": { - Input: ` context line -+new line 1 -+new line 2 - context line -`, - Fragment: TextFragment{ - OldLines: 2, - NewLines: 4, - }, - Output: &TextFragment{ - OldLines: 2, - NewLines: 4, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpAdd, "new line 1\n"}, - {OpAdd, "new line 2\n"}, - {OpContext, "context line\n"}, - }, - LinesAdded: 2, - LeadingContext: 1, - TrailingContext: 1, - }, - }, - "deleteWithContext": { - Input: ` context line --old line 1 --old line 2 - context line -`, - Fragment: TextFragment{ - OldLines: 4, - NewLines: 2, - }, - Output: &TextFragment{ - OldLines: 4, - NewLines: 2, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 1\n"}, - {OpDelete, "old line 2\n"}, - {OpContext, "context line\n"}, - }, - LinesDeleted: 2, - LeadingContext: 1, - TrailingContext: 1, - }, - }, - "replaceWithContext": { - Input: ` context line --old line 1 -+new line 1 - context line -`, - Fragment: TextFragment{ - OldLines: 3, - NewLines: 3, - }, - Output: &TextFragment{ - OldLines: 3, - NewLines: 3, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 1\n"}, - {OpAdd, "new line 1\n"}, - {OpContext, "context line\n"}, - }, - LinesDeleted: 1, - LinesAdded: 1, - LeadingContext: 1, - TrailingContext: 1, - }, - }, - "middleContext": { - Input: ` context line --old line 1 - context line -+new line 1 - context line -`, - Fragment: TextFragment{ - OldLines: 4, - NewLines: 4, - }, - Output: &TextFragment{ - OldLines: 4, - NewLines: 4, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 1\n"}, - {OpContext, "context line\n"}, - {OpAdd, "new line 1\n"}, - {OpContext, "context line\n"}, - }, - LinesDeleted: 1, - LinesAdded: 1, - LeadingContext: 1, - TrailingContext: 1, - }, - }, - "deleteFinalNewline": { - Input: ` context line --old line 1 -+new line 1 -\ No newline at end of file -`, - Fragment: TextFragment{ - OldLines: 2, - NewLines: 2, - }, - Output: &TextFragment{ - OldLines: 2, - NewLines: 2, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 1\n"}, - {OpAdd, "new line 1"}, - }, - LinesDeleted: 1, - LinesAdded: 1, - LeadingContext: 1, - }, - }, - "addFinalNewline": { - Input: ` context line --old line 1 -\ No newline at end of file -+new line 1 -`, - Fragment: TextFragment{ - OldLines: 2, - NewLines: 2, - }, - Output: &TextFragment{ - OldLines: 2, - NewLines: 2, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 1"}, - {OpAdd, "new line 1\n"}, - }, - LinesDeleted: 1, - LinesAdded: 1, - LeadingContext: 1, - }, - }, - "addAll": { - Input: `+new line 1 -+new line 2 -+new line 3 -`, - Fragment: TextFragment{ - OldLines: 0, - NewLines: 3, - }, - Output: &TextFragment{ - OldLines: 0, - NewLines: 3, - Lines: []Line{ - {OpAdd, "new line 1\n"}, - {OpAdd, "new line 2\n"}, - {OpAdd, "new line 3\n"}, - }, - LinesAdded: 3, - }, - }, - "deleteAll": { - Input: `-old line 1 --old line 2 --old line 3 -`, - Fragment: TextFragment{ - OldLines: 3, - NewLines: 0, - }, - Output: &TextFragment{ - OldLines: 3, - NewLines: 0, - Lines: []Line{ - {OpDelete, "old line 1\n"}, - {OpDelete, "old line 2\n"}, - {OpDelete, "old line 3\n"}, - }, - LinesDeleted: 3, - }, - }, - "emptyContextLine": { - Input: ` context line - -+new line - context line -`, - Fragment: TextFragment{ - OldLines: 3, - NewLines: 4, - }, - Output: &TextFragment{ - OldLines: 3, - NewLines: 4, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpContext, "\n"}, - {OpAdd, "new line\n"}, - {OpContext, "context line\n"}, - }, - LinesAdded: 1, - LeadingContext: 2, - TrailingContext: 1, - }, - }, - "emptyChunk": { - Input: "", - Err: true, - }, - "invalidOperation": { - Input: ` context line -?wat line - context line -`, - Fragment: TextFragment{ - OldLines: 3, - NewLines: 3, - }, - Err: true, - }, - "unbalancedHeader": { - Input: ` context line --old line 1 -+new line 1 - context line -`, - Fragment: TextFragment{ - OldLines: 2, - NewLines: 5, - }, - Err: true, - }, - "onlyContext": { - Input: ` context line - context line -`, - Fragment: TextFragment{ - OldLines: 2, - NewLines: 2, - }, - Err: true, - }, - "unexpectedNoNewlineMarker": { - Input: `\ No newline at end of file`, - Fragment: TextFragment{ - OldLines: 1, - NewLines: 1, - }, - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - frag := test.Fragment - err := p.ParseTextChunk(&frag) - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing text chunk, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("error parsing text chunk: %v", err) - } - - if !reflect.DeepEqual(test.Output, &frag) { - t.Errorf("incorrect fragment\nexpected: %+v\nactual: %+v", test.Output, &frag) - } - }) - } -} - -func TestParseTextFragments(t *testing.T) { - tests := map[string]struct { - Input string - File File - - Fragments []*TextFragment - Err bool - }{ - "multipleChanges": { - Input: `@@ -1,3 +1,2 @@ - context line --old line 1 - context line -@@ -8,3 +7,3 @@ - context line --old line 2 -+new line 1 - context line -@@ -15,3 +14,4 @@ - context line --old line 3 -+new line 2 -+new line 3 - context line -`, - Fragments: []*TextFragment{ - { - OldPosition: 1, - OldLines: 3, - NewPosition: 1, - NewLines: 2, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 1\n"}, - {OpContext, "context line\n"}, - }, - LinesDeleted: 1, - LeadingContext: 1, - TrailingContext: 1, - }, - { - OldPosition: 8, - OldLines: 3, - NewPosition: 7, - NewLines: 3, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 2\n"}, - {OpAdd, "new line 1\n"}, - {OpContext, "context line\n"}, - }, - LinesDeleted: 1, - LinesAdded: 1, - LeadingContext: 1, - TrailingContext: 1, - }, - { - OldPosition: 15, - OldLines: 3, - NewPosition: 14, - NewLines: 4, - Lines: []Line{ - {OpContext, "context line\n"}, - {OpDelete, "old line 3\n"}, - {OpAdd, "new line 2\n"}, - {OpAdd, "new line 3\n"}, - {OpContext, "context line\n"}, - }, - LinesDeleted: 1, - LinesAdded: 2, - LeadingContext: 1, - TrailingContext: 1, - }, - }, - }, - "badNewFile": { - Input: `@@ -1 +1,2 @@ --old line 1 -+new line 1 -+new line 2 -`, - File: File{ - IsNew: true, - }, - Err: true, - }, - "badDeletedFile": { - Input: `@@ -1,2 +1 @@ --old line 1 - context line -`, - File: File{ - IsDelete: true, - }, - Err: true, - }, - } - - for name, test := range tests { - t.Run(name, func(t *testing.T) { - p := newTestParser(test.Input, true) - - file := test.File - n, err := p.ParseTextFragments(&file) - if test.Err { - if err == nil || err == io.EOF { - t.Fatalf("expected error parsing text fragments, but got %v", err) - } - return - } - if err != nil { - t.Fatalf("error parsing text fragments: %v", err) - } - - if len(test.Fragments) != n { - t.Fatalf("incorrect number of added fragments: expected %d, actual %d", len(test.Fragments), n) - } - - for i, frag := range test.Fragments { - if !reflect.DeepEqual(frag, file.TextFragments[i]) { - t.Errorf("incorrect fragment at position %d\nexpected: %+v\nactual: %+v", i, frag, file.TextFragments[i]) - } - } - }) - } -} diff --git a/pkg/links/links.go b/pkg/links/links.go index 1bed63e..0795dfc 100644 --- a/pkg/links/links.go +++ b/pkg/links/links.go @@ -8,7 +8,7 @@ import ( "golang.org/x/net/html" - "github.com/antonmedv/gitmal/pkg/git" + "mokhan.ca/antonmedv/gitmal/pkg/git" ) type Set map[string]struct{} diff --git a/pkg/links/links_test.go b/pkg/links/links_test.go deleted file mode 100644 index 4d33c3f..0000000 --- a/pkg/links/links_test.go +++ /dev/null @@ -1,228 +0,0 @@ -package links - -import ( - "strings" - "testing" - - "github.com/antonmedv/gitmal/pkg/git" -) - -func buildTestSets(blobs []git.Blob) (Set, Set) { - dirs := BuildDirSet(blobs) - files := BuildFileSet(blobs) - return dirs, files -} - -func TestResolve_Links(t *testing.T) { - blobs := []git.Blob{ - {Path: "README.md"}, - {Path: "docs/intro.md"}, - {Path: "docs/getting-started.md"}, - {Path: "docs/faq.md"}, - {Path: "docs/tutorial/step1.md"}, - } - - dirs, files := buildTestSets(blobs) - - currentPath := "docs/intro.md" - rootHref := "../../" - ref := "master" - - tests := []struct { - name string - content string - wantContain []string - notContain []string - }{ - { - name: "relative link to existing .md file gets .html appended (per current transformHref)", - content: `<a href="getting-started.md">Getting started</a>`, - wantContain: []string{ - `href="../../blob/master/docs/getting-started.md.html"`, - }, - notContain: []string{ - `href="../../blob/master/docs/getting-started.md"`, - }, - }, - { - name: "relative link without extension to existing .md file gets .html appended", - content: `<a href="faq">FAQ</a>`, - wantContain: []string{ - `href="../../blob/master/docs/faq.md.html"`, - }, - notContain: []string{ - `href="faq">`, - }, - }, - { - name: "relative link to directory without trailing slash goes to /index.html", - content: `<a href="tutorial">Tutorial</a>`, - wantContain: []string{ - `href="../../blob/master/docs/tutorial/index.html"`, - }, - notContain: []string{ - `href="tutorial">`, - }, - }, - { - name: "relative link to directory with trailing slash goes to /index.html", - content: `<a href="tutorial/">Tutorial</a>`, - wantContain: []string{ - `href="../../blob/master/docs/tutorial/index.html"`, - }, - notContain: []string{ - `href="tutorial/">`, - }, - }, - { - name: "absolute http URL unchanged", - content: `<a href="https://example.org">External</a>`, - wantContain: []string{ - `href="https://example.org"`, - }, - }, - { - name: "root-relative link to repo file is resolved", - content: `<a href="/README.md">FAQ</a>`, - wantContain: []string{ - `href="../../blob/master/README.md.html"`, - }, - }, - { - name: "fragment-only href unchanged", - content: `<a href="#section1">Jump</a>`, - wantContain: []string{ - `href="#section1"`, - }, - }, - { - name: "mailto href unchanged", - content: `<a href="mailto:test@example.com">Mail</a>`, - wantContain: []string{ - `href="mailto:test@example.com"`, - }, - }, - { - name: "unknown relative path left untouched", - content: `<a href="unknown.md">Unknown</a>`, - wantContain: []string{ - `href="unknown.md"`, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := Resolve(tt.content, currentPath, rootHref, ref, dirs, files) - - for _, want := range tt.wantContain { - if !strings.Contains(got, want) { - t.Errorf("expected output to contain %q, got:\n%s", want, got) - } - } - for _, notWant := range tt.notContain { - if strings.Contains(got, notWant) { - t.Errorf("expected output NOT to contain %q, got:\n%s", notWant, got) - } - } - }) - } -} - -func TestResolve_Images(t *testing.T) { - // For image behavior we only care about currentPath/rootHref/ref, not dirs/files. - blobs := []git.Blob{ - {Path: "foo/bar/readme.md"}, - } - dirs, files := buildTestSets(blobs) - - rootHref := "../../" - ref := "master" - - t.Run("relative image src rewritten to raw URL with ref", func(t *testing.T) { - // current blob: foo/bar/readme.md - // img src: ../images/pic.png - // repoPath: foo/images/pic.png - // final: rootHref + "/raw/master/foo/images/pic.png" - content := `<p><img src="../images/pic.png" alt="Pic"></p>` - - got := Resolve(content, "foo/bar/readme.md", rootHref, ref, dirs, files) - - expected := `src="../../raw/master/foo/images/pic.png"` - if !strings.Contains(got, expected) { - t.Fatalf("expected output to contain %q, got:\n%s", expected, got) - } - }) - - t.Run("relative image src with ./ prefix", func(t *testing.T) { - content := `<p><img src="./img/logo.png"></p>` - - got := Resolve(content, "foo/readme.md", rootHref, ref, dirs, files) - - // repoPath: "foo/img/logo.png" - expected := `src="../../raw/master/foo/img/logo.png"` - if !strings.Contains(got, expected) { - t.Fatalf("expected output to contain %q, got:\n%s", expected, got) - } - }) - - t.Run("absolute image src unchanged, root-relative resolved from repo root", func(t *testing.T) { - content := ` -<p> - <img src="https://cdn.example.com/img.png"> - <img src="/static/logo.png"> -</p>` - - got := Resolve(content, "docs/intro.md", rootHref, ref, dirs, files) - - if !strings.Contains(got, `src="https://cdn.example.com/img.png"`) { - t.Errorf("expected absolute src to be unchanged, got:\n%s", got) - } - // root-relative should now point to raw/ref/... from repo root - if !strings.Contains(got, `src="../../raw/master/static/logo.png"`) { - t.Errorf("expected root-relative src to be resolved to raw URL, got:\n%s", got) - } - }) - - t.Run("image with query and fragment preserves them", func(t *testing.T) { - content := `<img src="../images/pic.png?size=large#anchor">` - - got := Resolve(content, "foo/bar/readme.md", rootHref, ref, dirs, files) - - if !strings.Contains(got, `src="../../raw/master/foo/images/pic.png?size=large#anchor"`) { - t.Errorf("expected src to be rewritten and keep query+fragment, got:\n%s", got) - } - }) -} - -func TestBuildDirSet(t *testing.T) { - blobs := []git.Blob{ - {Path: "a/b/c.md"}, - {Path: "a/d/e.md"}, - {Path: "x.md"}, - } - - dirs := BuildDirSet(blobs) - - wantDirs := []string{"a", "a/b", "a/d"} - for _, d := range wantDirs { - if _, ok := dirs[d]; !ok { - t.Errorf("expected dirs to contain %q", d) - } - } -} - -func TestBuildFileSet(t *testing.T) { - blobs := []git.Blob{ - {Path: "docs/intro.md"}, - {Path: "README.md"}, - } - - files := BuildFileSet(blobs) - - for _, p := range []string{"docs/intro.md", "README.md"} { - if _, ok := files[p]; !ok { - t.Errorf("expected files to contain %q", p) - } - } -} diff --git a/pkg/templates/blob.gohtml b/pkg/templates/blob.gohtml index 458a855..b98e2b3 100644 --- a/pkg/templates/blob.gohtml +++ b/pkg/templates/blob.gohtml @@ -1,4 +1,4 @@ -{{- /*gotype: github.com/antonmedv/gitmal/pkg/templates.BlobParams */ -}} +{{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.BlobParams */ -}} {{ define "head" }} <style> {{ .CSS }} diff --git a/pkg/templates/branches.gohtml b/pkg/templates/branches.gohtml index 9ffc091..743461d 100644 --- a/pkg/templates/branches.gohtml +++ b/pkg/templates/branches.gohtml @@ -1,4 +1,4 @@ -{{- /*gotype: github.com/antonmedv/gitmal/pkg/templates.BranchesParams*/ -}} +{{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.BranchesParams*/ -}} {{ define "head" }} <style> .branches { diff --git a/pkg/templates/commit.gohtml b/pkg/templates/commit.gohtml index d5c6b37..3176f97 100644 --- a/pkg/templates/commit.gohtml +++ b/pkg/templates/commit.gohtml @@ -1,4 +1,4 @@ -{{- /*gotype: github.com/antonmedv/gitmal/pkg/templates.CommitParams*/ -}} +{{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.CommitParams*/ -}} {{ define "head" }} <style> h1 code { diff --git a/pkg/templates/commits_list.gohtml b/pkg/templates/commits_list.gohtml index 21d3ab2..76dd43c 100644 --- a/pkg/templates/commits_list.gohtml +++ b/pkg/templates/commits_list.gohtml @@ -1,4 +1,4 @@ -{{- /*gotype: github.com/antonmedv/gitmal/pkg/templates.CommitsListParams*/ -}} +{{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.CommitsListParams*/ -}} {{ define "head" }} <style> .commits { diff --git a/pkg/templates/file_tree.gohtml b/pkg/templates/file_tree.gohtml index f096ecb..21fc07c 100644 --- a/pkg/templates/file_tree.gohtml +++ b/pkg/templates/file_tree.gohtml @@ -1,4 +1,4 @@ -{{- /*gotype:github.com/antonmedv/gitmal/pkg/templates.FileTreeParams*/ -}} +{{- /*gotype:mokhan.ca/antonmedv/gitmal/pkg/templates.FileTreeParams*/ -}} {{ define "file_tree" }} {{ range .Nodes }} {{ if .IsDir }} diff --git a/pkg/templates/header.gohtml b/pkg/templates/header.gohtml index e326c43..4b5af05 100644 --- a/pkg/templates/header.gohtml +++ b/pkg/templates/header.gohtml @@ -1,4 +1,4 @@ -{{- /*gotype: github.com/antonmedv/gitmal/pkg/templates.HeaderParams*/ -}} +{{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.HeaderParams*/ -}} {{ define "header" }} <div class="header-container"> <header> diff --git a/pkg/templates/layout.gohtml b/pkg/templates/layout.gohtml index cefc24d..9438396 100644 --- a/pkg/templates/layout.gohtml +++ b/pkg/templates/layout.gohtml @@ -1,4 +1,4 @@ -{{- /*gotype: github.com/antonmedv/gitmal/pkg/templates.LayoutParams*/ -}} +{{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.LayoutParams*/ -}} <!DOCTYPE html> <html lang="en"> <head> @@ -313,7 +313,6 @@ </div> </main> <footer> - Generated by <a href="https://github.com/antonmedv/gitmal">Gitmal</a> </footer> </body> </html> diff --git a/pkg/templates/list.gohtml b/pkg/templates/list.gohtml index 9955260..9780504 100644 --- a/pkg/templates/list.gohtml +++ b/pkg/templates/list.gohtml @@ -1,4 +1,4 @@ -{{- /*gotype: github.com/antonmedv/gitmal/pkg/templates.ListParams*/ -}} +{{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.ListParams*/ -}} {{ define "head" }} <style> .files { diff --git a/pkg/templates/markdown.gohtml b/pkg/templates/markdown.gohtml index 782e993..7827950 100644 --- a/pkg/templates/markdown.gohtml +++ b/pkg/templates/markdown.gohtml @@ -1,4 +1,4 @@ -{{- /*gotype: github.com/antonmedv/gitmal/pkg/templates.MarkdownParams*/ -}} +{{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.MarkdownParams*/ -}} {{ define "head" }} <style> [id] { diff --git a/pkg/templates/preview.gohtml b/pkg/templates/preview.gohtml index 0f9b78c..bc6f898 100644 --- a/pkg/templates/preview.gohtml +++ b/pkg/templates/preview.gohtml @@ -1,4 +1,4 @@ -{{- /*gotype: github.com/antonmedv/gitmal/pkg/templates.PreviewParams*/ -}} +{{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.PreviewParams*/ -}} <!DOCTYPE html> <html lang="en"> <head> diff --git a/pkg/templates/tags.gohtml b/pkg/templates/tags.gohtml index 32f8e0b..97b77b0 100644 --- a/pkg/templates/tags.gohtml +++ b/pkg/templates/tags.gohtml @@ -1,4 +1,4 @@ -{{- /*gotype: github.com/antonmedv/gitmal/pkg/templates.TagsParams*/ -}} +{{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.TagsParams*/ -}} {{ define "head" }} <style> .tags { diff --git a/pkg/templates/templates.go b/pkg/templates/templates.go index 91d4884..593f0a3 100644 --- a/pkg/templates/templates.go +++ b/pkg/templates/templates.go @@ -7,7 +7,7 @@ import ( "path/filepath" "time" - "github.com/antonmedv/gitmal/pkg/git" + "mokhan.ca/antonmedv/gitmal/pkg/git" ) var funcs = FuncMap{ diff --git a/post_process.go b/post_process.go index 392fa74..895d933 100644 --- a/post_process.go +++ b/post_process.go @@ -16,7 +16,7 @@ import ( "github.com/tdewolff/minify/v2/html" "github.com/tdewolff/minify/v2/svg" - "github.com/antonmedv/gitmal/pkg/progress_bar" + "mokhan.ca/antonmedv/gitmal/pkg/progress_bar" ) func postProcessHTML(root string, doMinify bool, doGzip bool) error { @@ -5,8 +5,8 @@ import ( "html/template" "strings" - "github.com/antonmedv/gitmal/pkg/git" - "github.com/antonmedv/gitmal/pkg/links" + "mokhan.ca/antonmedv/gitmal/pkg/git" + "mokhan.ca/antonmedv/gitmal/pkg/links" ) func readme(files []git.Blob, dirsSet, filesSet links.Set, params Params, rootHref string) template.HTML { @@ -5,8 +5,8 @@ import ( "os" "path/filepath" - "github.com/antonmedv/gitmal/pkg/git" - "github.com/antonmedv/gitmal/pkg/templates" + "mokhan.ca/antonmedv/gitmal/pkg/git" + "mokhan.ca/antonmedv/gitmal/pkg/templates" ) func generateTags(entries []git.Tag, params Params) error { @@ -11,7 +11,7 @@ import ( "github.com/alecthomas/chroma/v2/lexers" "github.com/alecthomas/chroma/v2/styles" - "github.com/antonmedv/gitmal/pkg/templates" + "mokhan.ca/antonmedv/gitmal/pkg/templates" ) var themeStyles = map[string]string{ @@ -6,8 +6,8 @@ import ( "path/filepath" "strings" - "github.com/antonmedv/gitmal/pkg/git" - "github.com/antonmedv/gitmal/pkg/templates" + "mokhan.ca/antonmedv/gitmal/pkg/git" + "mokhan.ca/antonmedv/gitmal/pkg/templates" ) const dot = "ยท" |
