Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package glab for openSUSE:Factory checked in at 2025-08-04 15:24:59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/glab (Old) and /work/SRC/openSUSE:Factory/.glab.new.1085 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "glab" Mon Aug 4 15:24:59 2025 rev:54 rq:1297343 version:1.65.0 Changes: -------- --- /work/SRC/openSUSE:Factory/glab/glab.changes 2025-07-31 17:50:20.538479577 +0200 +++ /work/SRC/openSUSE:Factory/.glab.new.1085/glab.changes 2025-08-04 15:25:32.783817440 +0200 @@ -1,0 +2,12 @@ +Fri Aug 01 08:14:10 UTC 2025 - Johannes Kastl <opensuse_buildserv...@ojkastl.de> + +- Update to version 1.65.0: + * fix(get-token): gracefully handle concurrent token cache writes + * feat(issue-update): add due-date functionality + * chore(deps): update module github.com/docker/cli to + v28.3.3+incompatible + * feat(issue): Remove --label and --not-label mutual exclusivity + * feat(mr): display file and line context for code comments + * feat(job artifact): Add --list-paths to print paths + +------------------------------------------------------------------- Old: ---- glab-1.64.0.obscpio New: ---- glab-1.65.0.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ glab.spec ++++++ --- /var/tmp/diff_new_pack.ijJVMz/_old 2025-08-04 15:25:34.471888349 +0200 +++ /var/tmp/diff_new_pack.ijJVMz/_new 2025-08-04 15:25:34.471888349 +0200 @@ -18,7 +18,7 @@ Name: glab -Version: 1.64.0 +Version: 1.65.0 Release: 0 Summary: A GitLab command line tool License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.ijJVMz/_old 2025-08-04 15:25:34.519890366 +0200 +++ /var/tmp/diff_new_pack.ijJVMz/_new 2025-08-04 15:25:34.523890533 +0200 @@ -3,7 +3,7 @@ <param name="url">https://gitlab.com/gitlab-org/cli.git</param> <param name="scm">git</param> <param name="package-meta">yes</param> - <param name="revision">v1.64.0</param> + <param name="revision">v1.65.0</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.ijJVMz/_old 2025-08-04 15:25:34.551891710 +0200 +++ /var/tmp/diff_new_pack.ijJVMz/_new 2025-08-04 15:25:34.551891710 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://gitlab.com/gitlab-org/cli.git</param> - <param name="changesrevision">fe60bcf75bfb58801f5a429a52a3461ef62b0f6e</param></service></servicedata> + <param name="changesrevision">8514bc42ef2c15a0ff27782a22b3add584b0d21c</param></service></servicedata> (No newline at EOF) ++++++ glab-1.64.0.obscpio -> glab-1.65.0.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/.git/HEAD new/glab-1.65.0/.git/HEAD --- old/glab-1.64.0/.git/HEAD 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/.git/HEAD 2025-07-29 14:35:18.000000000 +0200 @@ -1 +1 @@ -fe60bcf75bfb58801f5a429a52a3461ef62b0f6e +8514bc42ef2c15a0ff27782a22b3add584b0d21c diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/.git/ORIG_HEAD new/glab-1.65.0/.git/ORIG_HEAD --- old/glab-1.64.0/.git/ORIG_HEAD 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/.git/ORIG_HEAD 2025-07-29 14:35:18.000000000 +0200 @@ -1 +1 @@ -fe60bcf75bfb58801f5a429a52a3461ef62b0f6e +8514bc42ef2c15a0ff27782a22b3add584b0d21c Binary files old/glab-1.64.0/.git/index and new/glab-1.65.0/.git/index differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/.git/logs/HEAD new/glab-1.65.0/.git/logs/HEAD --- old/glab-1.64.0/.git/logs/HEAD 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/.git/logs/HEAD 2025-07-29 14:35:18.000000000 +0200 @@ -1,2 +1,2 @@ -0000000000000000000000000000000000000000 6dd100b9866275cfef3b42b067658e45fe52e0ac kastl <kastl@tumbleweed-pkg.baten> 1753343254 +0200 clone: from https://gitlab.com/gitlab-org/cli.git -6dd100b9866275cfef3b42b067658e45fe52e0ac fe60bcf75bfb58801f5a429a52a3461ef62b0f6e kastl <kastl@tumbleweed-pkg.baten> 1753343254 +0200 checkout: moving from main to v1.64.0 +0000000000000000000000000000000000000000 2a4f6fc98c654a657a9e6dcbfd4c713dd5e95006 kastl <kastl@tumbleweed-pkg.baten> 1754036050 +0200 clone: from https://gitlab.com/gitlab-org/cli.git +2a4f6fc98c654a657a9e6dcbfd4c713dd5e95006 8514bc42ef2c15a0ff27782a22b3add584b0d21c kastl <kastl@tumbleweed-pkg.baten> 1754036050 +0200 checkout: moving from main to v1.65.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/.git/logs/refs/heads/main new/glab-1.65.0/.git/logs/refs/heads/main --- old/glab-1.64.0/.git/logs/refs/heads/main 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/.git/logs/refs/heads/main 2025-07-29 14:35:18.000000000 +0200 @@ -1 +1 @@ -0000000000000000000000000000000000000000 6dd100b9866275cfef3b42b067658e45fe52e0ac kastl <kastl@tumbleweed-pkg.baten> 1753343254 +0200 clone: from https://gitlab.com/gitlab-org/cli.git +0000000000000000000000000000000000000000 2a4f6fc98c654a657a9e6dcbfd4c713dd5e95006 kastl <kastl@tumbleweed-pkg.baten> 1754036050 +0200 clone: from https://gitlab.com/gitlab-org/cli.git diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/.git/logs/refs/remotes/origin/HEAD new/glab-1.65.0/.git/logs/refs/remotes/origin/HEAD --- old/glab-1.64.0/.git/logs/refs/remotes/origin/HEAD 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/.git/logs/refs/remotes/origin/HEAD 2025-07-29 14:35:18.000000000 +0200 @@ -1 +1 @@ -0000000000000000000000000000000000000000 6dd100b9866275cfef3b42b067658e45fe52e0ac kastl <kastl@tumbleweed-pkg.baten> 1753343254 +0200 clone: from https://gitlab.com/gitlab-org/cli.git +0000000000000000000000000000000000000000 2a4f6fc98c654a657a9e6dcbfd4c713dd5e95006 kastl <kastl@tumbleweed-pkg.baten> 1754036050 +0200 clone: from https://gitlab.com/gitlab-org/cli.git Binary files old/glab-1.64.0/.git/objects/pack/pack-42b832dc237d283c13321b8c84f203544f1512b9.idx and new/glab-1.65.0/.git/objects/pack/pack-42b832dc237d283c13321b8c84f203544f1512b9.idx differ Binary files old/glab-1.64.0/.git/objects/pack/pack-42b832dc237d283c13321b8c84f203544f1512b9.pack and new/glab-1.65.0/.git/objects/pack/pack-42b832dc237d283c13321b8c84f203544f1512b9.pack differ Binary files old/glab-1.64.0/.git/objects/pack/pack-42b832dc237d283c13321b8c84f203544f1512b9.rev and new/glab-1.65.0/.git/objects/pack/pack-42b832dc237d283c13321b8c84f203544f1512b9.rev differ Binary files old/glab-1.64.0/.git/objects/pack/pack-c95635a86c85bc39ae17a95aee9cc547539c7e49.idx and new/glab-1.65.0/.git/objects/pack/pack-c95635a86c85bc39ae17a95aee9cc547539c7e49.idx differ Binary files old/glab-1.64.0/.git/objects/pack/pack-c95635a86c85bc39ae17a95aee9cc547539c7e49.pack and new/glab-1.65.0/.git/objects/pack/pack-c95635a86c85bc39ae17a95aee9cc547539c7e49.pack differ Binary files old/glab-1.64.0/.git/objects/pack/pack-c95635a86c85bc39ae17a95aee9cc547539c7e49.rev and new/glab-1.65.0/.git/objects/pack/pack-c95635a86c85bc39ae17a95aee9cc547539c7e49.rev differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/.git/packed-refs new/glab-1.65.0/.git/packed-refs --- old/glab-1.64.0/.git/packed-refs 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/.git/packed-refs 2025-07-29 14:35:18.000000000 +0200 @@ -23,6 +23,7 @@ 249472d4a6b6fbac729c18206165cbfd7442044b refs/remotes/origin/add-danger-review 340ccf35887dc1039801bc6c1b3c509781440eff refs/remotes/origin/add-golangci-lint 05efbe457812da81fbb75b4e68292e77a3e5917d refs/remotes/origin/am-adding-shell-assistant-scripts +de3083ac94ea5108139f24c6b654fc800205d059 refs/remotes/origin/ash2k/roots fb4db5b4998ab654ed3183592a5fff355a7d068c refs/remotes/origin/build-with-framework 32d5ec3d0183028539b3ab98f4746feca19ca47f refs/remotes/origin/bump-go-gitlab df39df4c6b4a8987fa1320e17ae9f28a5b1f8d46 refs/remotes/origin/bwil/test-fmt-failing-job @@ -41,8 +42,7 @@ 88df561ca57b6f7f9b45f28cfffed6d95c4dcb3c refs/remotes/origin/docs-markdown f4c4781693a194664201f44a5330b42f9f0cf4da refs/remotes/origin/faleksic-ci-status-default-repo 72bc4589228cfdcb20481dc2bb85b18d0cdeff09 refs/remotes/origin/faleksic-glamour-markdown -facb124145249d317d09724c18874ce073e54030 refs/remotes/origin/faleksic-remove-shorthand-h -e79de4f6be2f1f9b65fab4f884ab27bcb2946c5a refs/remotes/origin/feat/remove-label-and-not-label-mutual-exclusivity +b229debc0c36df135ce35f3362a5977124f6af0c refs/remotes/origin/faleksic-remove-shorthand-h d3409aee5d5d6d435cc9bf7231b8a63db04928ba refs/remotes/origin/fix-7235-debug 02388706d5d43148a65a3009fa8ec64eea13b3a5 refs/remotes/origin/fvpotvin-remove-dpop-package 0329bac7147fa1a3088ff0ca26fe3d4c46eacf29 refs/remotes/origin/gary-stack-test-1ebae4eb @@ -64,7 +64,7 @@ 5106fce6ca6db24d33cca59991dd2e46ad5c8e2e refs/remotes/origin/gmh-cli-remove-debug-reduce-file-size d238c9e35d769aa1b5f877dbc87b9c3b6a0ac79a refs/remotes/origin/gmh-fallback-to-help-for-missing-api-args 5962cfe1da1190744e5b4f5bac350ed5253bb47f refs/remotes/origin/gmh-fix-graphql-pathescapes -133822fb198f1e962a5bd6c4697a5d271ae8bd99 refs/remotes/origin/gmh-git-mocks-part-2 +3d0d4f10d45b435729311084f597ae55113cdd8e refs/remotes/origin/gmh-git-mocks-part-2 a84c23f7fba3b32954ab5807854cf54ecc3796cb refs/remotes/origin/gmh-git-mocks-part-3 6f061cdfc6ad63d666c7d6e3f894a8d2a6f55f3c refs/remotes/origin/gmh-git-mocks-part-4 8f094bd1f62ad3cdd5be3791efba6c3f29b3394c refs/remotes/origin/gmh-goreleaser-additions @@ -78,6 +78,7 @@ 67c2db6a7e71f763ab5bd5d14425a1074b1650a3 refs/remotes/origin/gmh-windows-checksum c0bc82fc2b9ab30dcc640771718e366ef6c432ad refs/remotes/origin/hacks4oats/stacked-diff-command c36d3a1e8b965f03ad1ba3259109670c5e346815 refs/remotes/origin/hkhanna2_workspaces_commands +0c22c049cb1cc0772baa493d814e5177b827a8f0 refs/remotes/origin/honor-api-hostname 82da7c3031c01344f0b0d3b97d69eb55837e7cba refs/remotes/origin/if-7444-gcp_create_wlif 8ab08fa81f49ef3a0a6d2f397b06830b04405e68 refs/remotes/origin/if-7445-gcp_create_iam_policy b31a351523d837f7a66a48a9ac336ee9c5bee4e7 refs/remotes/origin/jburnett/ssh @@ -88,13 +89,14 @@ c522100a166bf0a5710e893cd4d9eb685372eb99 refs/remotes/origin/jmc-open-mr-web a4423d4d5aad1a43ce0614759ba631ff4bd387a0 refs/remotes/origin/jmc-release-broke aa0cc8bcf5caaf2e6c324fadf8f1bd4bb0ae7818 refs/remotes/origin/jmc-run-lint-int-test +25cba06d3a1e3bb684525723ed6476339b8303a4 refs/remotes/origin/jmc-staging-test f99f9844006aaafd44cb67cf5b7726c042cba7b5 refs/remotes/origin/jmc-verbose-apk-add bab7ffe59702bef942070bb8a2fd3916cf87b1e8 refs/remotes/origin/json-output-tests 873dc2207f3c0a15ee44e106086750fe49a7c988 refs/remotes/origin/julian/defer 5b2efd0f460c99b5af28ac44a0a6177ccab9d0e0 refs/remotes/origin/julian/error fbcfd98947286b0043e4c3c370e174b86cb1a7f2 refs/remotes/origin/julian/limitedreader 5846dfbbca64b0dec4a193c7cfe9ebfbf97e0b45 refs/remotes/origin/jy-compare -6dd100b9866275cfef3b42b067658e45fe52e0ac refs/remotes/origin/main +2a4f6fc98c654a657a9e6dcbfd4c713dd5e95006 refs/remotes/origin/main 757c80f0872eb2861d4e49ea491fae8fdf8bd40a refs/remotes/origin/master 1ca15d4ed9cb19ce355d2a33fba658fd80f0e740 refs/remotes/origin/msj-linux-links 46ba6fefaefbb458bcc36a687e679c5b512f2cf6 refs/remotes/origin/nagyv-agent-bootstrap @@ -104,7 +106,6 @@ 6f7fea9fd1652a7a5cdc01bae5ad5e44e0ba36ff refs/remotes/origin/phikai-add-danger-reviews 1e232dbbe64f29d9fd6b11808b8efb7ee24dd945 refs/remotes/origin/phikai-doc-job-test 0adfc6f7f1610a2d8566d9ee5f0cd5b7b1baf6eb refs/remotes/origin/phikai-docs-linting -f6837d926f04aa07538e539557638d283a741eba refs/remotes/origin/phikai-improve-token-validation 984b08c15b88f9803e6d7865e3de2af16b5725aa refs/remotes/origin/phikai-install-docker-version 4ea230efe7b31f6a9d8b3009f84f50bf7e5d2928 refs/remotes/origin/phikai-issue-links 43fc715a02c0e21ca29875f01f13ee22aa0ae84f refs/remotes/origin/phikai-issue-update-links @@ -212,6 +213,7 @@ 1df2df0d0eb78a74351ca2d963c7b6c0671eda64 refs/tags/v1.62.0 1db67b8fabc4a2cd5227579f0ab234c0475feed6 refs/tags/v1.63.0 fe60bcf75bfb58801f5a429a52a3461ef62b0f6e refs/tags/v1.64.0 +8514bc42ef2c15a0ff27782a22b3add584b0d21c refs/tags/v1.65.0 87ca9a49647c35c25d863935813c99a7422f4b64 refs/tags/v1.7.0 e1d55b31af929c72ad367e551b6e1120d8605b66 refs/tags/v1.7.1 6a4cffd93da79f5e47b51f0443d32a55fc6749ed refs/tags/v1.8.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/.git/refs/heads/main new/glab-1.65.0/.git/refs/heads/main --- old/glab-1.64.0/.git/refs/heads/main 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/.git/refs/heads/main 2025-07-29 14:35:18.000000000 +0200 @@ -1 +1 @@ -6dd100b9866275cfef3b42b067658e45fe52e0ac +2a4f6fc98c654a657a9e6dcbfd4c713dd5e95006 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/docs/source/issue/update.md new/glab-1.65.0/docs/source/issue/update.md --- old/glab-1.64.0/docs/source/issue/update.md 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/docs/source/issue/update.md 2025-07-29 14:35:18.000000000 +0200 @@ -31,6 +31,7 @@ -a, --assignee strings Assign users by username. Prefix with '!' or '-' to remove from existing assignees, or '+' to add new. Otherwise, replace existing assignees with these users. -c, --confidential Make issue confidential -d, --description string Issue description. Set to "-" to open an editor. + --due-date string A date in 'YYYY-MM-DD' format. -l, --label strings Add labels. --lock-discussion Lock discussion on issue. -m, --milestone string Title of the milestone to assign Set to "" or 0 to unassign. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/docs/source/job/artifact.md new/glab-1.65.0/docs/source/job/artifact.md --- old/glab-1.64.0/docs/source/job/artifact.md 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/docs/source/job/artifact.md 2025-07-29 14:35:18.000000000 +0200 @@ -28,12 +28,14 @@ ```console $ glab job artifact main build $ glab job artifact main deploy --path="artifacts/" +$ glab job artifact main deploy --list-paths ``` ## Options ```plaintext + -l, --list-paths Print the paths of downloaded artifacts. -p, --path string Path to download the artifact files. (default "./") ``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/go.mod new/glab-1.65.0/go.mod --- old/glab-1.64.0/go.mod 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/go.mod 2025-07-29 14:35:18.000000000 +0200 @@ -11,7 +11,7 @@ github.com/charmbracelet/glamour v0.10.0 github.com/coder/websocket v1.8.13 github.com/cyphar/filepath-securejoin v0.4.1 - github.com/docker/cli v28.3.2+incompatible + github.com/docker/cli v28.3.3+incompatible github.com/docker/docker-credential-helpers v0.9.3 github.com/dustin/go-humanize v1.0.1 github.com/gdamore/tcell/v2 v2.8.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/go.sum new/glab-1.65.0/go.sum --- old/glab-1.64.0/go.sum 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/go.sum 2025-07-29 14:35:18.000000000 +0200 @@ -69,8 +69,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/docker/cli v28.3.2+incompatible h1:mOt9fcLE7zaACbxW1GeS65RI67wIJrTnqS3hP2huFsY= -github.com/docker/cli v28.3.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v28.3.3+incompatible h1:fp9ZHAr1WWPGdIWBM1b3zLtgCF+83gRdVMTJsUeiyAo= +github.com/docker/cli v28.3.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8= github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo= github.com/dop251/goja v0.0.0-20240927123429-241b342198c2 h1:Ux9RXuPQmTB4C1MKagNLme0krvq8ulewfor+ORO/QL4= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/internal/commands/ci/artifact/artifact.go new/glab-1.65.0/internal/commands/ci/artifact/artifact.go --- old/glab-1.64.0/internal/commands/ci/artifact/artifact.go 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/internal/commands/ci/artifact/artifact.go 2025-07-29 14:35:18.000000000 +0200 @@ -33,7 +33,7 @@ return err } - return jobArtifact.DownloadArtifacts(apiClient, repo, path, args[0], args[1]) + return jobArtifact.DownloadArtifacts(apiClient, repo, path, false, args[0], args[1]) }, Deprecated: "use 'glab job artifact' instead.", } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/internal/commands/cluster/agent/get_token/cache.go new/glab-1.65.0/internal/commands/cluster/agent/get_token/cache.go --- old/glab-1.64.0/internal/commands/cluster/agent/get_token/cache.go 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/internal/commands/cluster/agent/get_token/cache.go 2025-07-29 14:35:18.000000000 +0200 @@ -91,13 +91,20 @@ return io.ReadAll(file) } -func (f *fileStorage) set(id string, data []byte) error { +func (f *fileStorage) set(id string, data []byte) (err error) { // TODO: handle race conditions, yes renaming a file is most often atomic, but not always // and it's unclear how it should be handled - should the content of the existing file be // read in case of a conflict? But what if the file is not yet fully written? // There are open questions that can be answered and implemented in a follow up iteration. - file, err := f.root.OpenFile(id, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o400) + var file *os.File + file, err = f.root.OpenFile(id, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o400) if err != nil { + if errors.Is(err, os.ErrExist) { + // NOTE: this may happen on concurrent runs, we just won't write the + // file and rely on the concurrent process to have it done correctly + // and we let the caller use the token they produce this time. + return nil + } return err } defer func() { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/internal/commands/issuable/list/issuable_list.go new/glab-1.65.0/internal/commands/issuable/list/issuable_list.go --- old/glab-1.64.0/internal/commands/issuable/list/issuable_list.go 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/internal/commands/issuable/list/issuable_list.go 2025-07-29 14:35:18.000000000 +0200 @@ -85,12 +85,6 @@ `, issueType)), Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { - if len(opts.Labels) != 0 && len(opts.NotLabels) != 0 { - return cmdutils.FlagError{ - Err: errors.New("flags --label and --not-label are mutually exclusive."), - } - } - if opts.Author != "" && len(opts.NotAuthor) != 0 { return cmdutils.FlagError{ Err: errors.New("flags --author and --not-author are mutually exclusive."), @@ -431,12 +425,6 @@ if opts.NotAuthorID != nil && issue.Author != nil && issue.Author.ID == *opts.NotAuthorID { return false } - if opts.Labels != nil && !hasAllLabels(issue, []string(*opts.Labels)) { - return false - } - if opts.NotLabels != nil && hasAnyLabel(issue, []string(*opts.NotLabels)) { - return false - } if opts.Milestone != nil && (issue.Milestone == nil || !strings.EqualFold(issue.Milestone.Title, *opts.Milestone)) { return false } @@ -478,36 +466,6 @@ } } -func hasAllLabels(issue *gitlab.Issue, labels []string) bool { - issueLabels := make(map[string]bool) - for _, l := range issue.Labels { - issueLabels[l] = true - } - - for _, l := range labels { - if _, ok := issueLabels[l]; !ok { - return false - } - } - - return true -} - -func hasAnyLabel(issue *gitlab.Issue, labels []string) bool { - issueLabels := make(map[string]bool) - for _, l := range issue.Labels { - issueLabels[l] = true - } - - for _, l := range labels { - if _, ok := issueLabels[l]; ok { - return true - } - } - - return false -} - func projectListIssueOptionsToGroup(l *gitlab.ListProjectIssuesOptions) *gitlab.ListGroupIssuesOptions { var assigneeID *gitlab.AssigneeIDValue if l.AssigneeID != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/internal/commands/issuable/list/issuable_list_test.go new/glab-1.65.0/internal/commands/issuable/list/issuable_list_test.go --- old/glab-1.64.0/internal/commands/issuable/list/issuable_list_test.go 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/internal/commands/issuable/list/issuable_list_test.go 2025-07-29 14:35:18.000000000 +0200 @@ -20,6 +20,7 @@ "github.com/MakeNowJust/heredoc/v2" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" gitlab "gitlab.com/gitlab-org/api/client-go" "gitlab.com/gitlab-org/cli/internal/api" "gitlab.com/gitlab-org/cli/internal/testing/httpmock" @@ -507,16 +508,6 @@ wantIDs: []int{2}, }, { - name: "label flag", - commandLine: `--group testGroupID --epic 42 --all --label 'label::one'`, - wantIDs: []int{1}, - }, - { - name: "not-label flag", - commandLine: `--group testGroupID --epic 42 --all --not-label 'label::one'`, - wantIDs: []int{2}, - }, - { name: "milestone flag", commandLine: `--group testGroupID --epic 42 --all --milestone 'milestone one'`, wantIDs: []int{1}, @@ -589,6 +580,163 @@ }) } } + +func TestIssueList_filterByLabel(t *testing.T) { + t.Parallel() + tests := map[string]struct { + reqURL string + respStatus int + respBody []*gitlab.Issue + args string + expect []int + }{ + "with --label": { + reqURL: `/api/v4/groups/testGroupID/epics/42/issues?page=1&per_page=30`, + respStatus: http.StatusOK, + respBody: []*gitlab.Issue{ + { + IID: 1, + State: "opened", + Assignees: []*gitlab.IssueAssignee{ + {ID: 101}, + }, + Author: &gitlab.IssueAuthor{ID: 102}, + Labels: gitlab.Labels{"label::one"}, + Milestone: &gitlab.Milestone{ + Title: "Milestone one", + }, + Title: "This is issue one", + Iteration: &gitlab.GroupIteration{ + ID: 103, + }, + Confidential: false, + }, + { + IID: 2, + State: "open", + Assignees: []*gitlab.IssueAssignee{ + {ID: 101}, + }, + Author: &gitlab.IssueAuthor{ID: 102}, + Labels: gitlab.Labels{"label::one"}, + Milestone: &gitlab.Milestone{ + Title: "Milestone two", + }, + Title: "That is issue two", + Iteration: &gitlab.GroupIteration{ + ID: 203, + }, + Confidential: false, + }, + }, + args: "--group testGroupID --epic 42 --all --label label::one", + expect: []int{1, 2}, + }, + "with --not-label": { + reqURL: `/api/v4/groups/testGroupID/epics/42/issues?page=1&per_page=30`, + respStatus: http.StatusOK, + respBody: []*gitlab.Issue{ + { + IID: 3, + State: "open", + Assignees: []*gitlab.IssueAssignee{ + {ID: 101}, + }, + Author: &gitlab.IssueAuthor{ID: 102}, + Labels: gitlab.Labels{"label::two"}, + Milestone: &gitlab.Milestone{ + Title: "Milestone two", + }, + Title: "That is issue three", + Iteration: &gitlab.GroupIteration{ + ID: 303, + }, + Confidential: false, + }, + }, + args: "--group testGroupID --epic 42 --all --not-label label::one", + expect: []int{3}, + }, + "with --label and --not-label": { + reqURL: `/api/v4/groups/testGroupID/epics/42/issues?page=1&per_page=30`, + respStatus: http.StatusOK, + respBody: []*gitlab.Issue{ + { + IID: 1, + State: "opened", + Assignees: []*gitlab.IssueAssignee{ + {ID: 101}, + }, + Author: &gitlab.IssueAuthor{ID: 102}, + Labels: gitlab.Labels{"label::one"}, + Milestone: &gitlab.Milestone{ + Title: "Milestone one", + }, + Title: "This is issue one", + Iteration: &gitlab.GroupIteration{ + ID: 103, + }, + Confidential: false, + }, + { + IID: 2, + State: "open", + Assignees: []*gitlab.IssueAssignee{ + {ID: 101}, + }, + Author: &gitlab.IssueAuthor{ID: 102}, + Labels: gitlab.Labels{"label::one"}, + Milestone: &gitlab.Milestone{ + Title: "Milestone two", + }, + Title: "That is issue two", + Iteration: &gitlab.GroupIteration{ + ID: 203, + }, + Confidential: false, + }, + { + IID: 3, + State: "open", + Assignees: []*gitlab.IssueAssignee{ + {ID: 101}, + }, + Author: &gitlab.IssueAuthor{ID: 102}, + Labels: gitlab.Labels{"label::two"}, + Milestone: &gitlab.Milestone{ + Title: "Milestone two", + }, + Title: "That is issue three", + Iteration: &gitlab.GroupIteration{ + ID: 303, + }, + Confidential: false, + }, + }, + args: "--group testGroupID --epic 42 --all --label label::one --not-label label::three", + expect: []int{1, 2, 3}, + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + fakeHTTP := &httpmock.Mocker{ + MatchURL: httpmock.PathAndQuerystring, + } + defer fakeHTTP.Verify(t) + + fakeHTTP.RegisterResponder(http.MethodGet, tt.reqURL, httpmock.NewJSONResponse(tt.respStatus, tt.respBody)) + out, err := runCommand(t, "issue", fakeHTTP, true, tt.args+" --output-format ids", "") + require.NoError(t, err, "command: %s err: %v", tt.args, err) + require.Emptyf(t, out.Stderr(), "command: %s stderr: %s", tt.args, out.Stderr()) + + got, err := strToIntSlice(out.String()) + require.NoErrorf(t, err, "command: %s output:\n%s", tt.args, out) + + assert.Equal(t, tt.expect, got) + }) + } +} func strToIntSlice(s string) ([]int, error) { var ret []int diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/internal/commands/issue/update/issue_update.go new/glab-1.65.0/internal/commands/issue/update/issue_update.go --- old/glab-1.64.0/internal/commands/issue/update/issue_update.go 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/internal/commands/issue/update/issue_update.go 2025-07-29 14:35:18.000000000 +0200 @@ -170,6 +170,14 @@ } } } + if m, _ := cmd.Flags().GetString("due-date"); m != "" { + actions = append(actions, "added due date") + dueDate, err := gitlab.ParseISOTime(m) + if err != nil { + return err + } + l.DueDate = gitlab.Ptr(dueDate) + } fmt.Fprintf(out, "- Updating issue #%d\n", issue.IID) @@ -200,6 +208,7 @@ StringSliceP("assignee", "a", []string{}, "Assign users by username. Prefix with '!' or '-' to remove from existing assignees, or '+' to add new. Otherwise, replace existing assignees with these users.") issueUpdateCmd.Flags().Bool("unassign", false, "Unassign all users.") issueUpdateCmd.Flags().IntP("weight", "w", 0, "Set weight of the issue.") + issueUpdateCmd.Flags().StringP("due-date", "", "", "A date in 'YYYY-MM-DD' format.") return issueUpdateCmd } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/internal/commands/issue/update/issue_update_integration_test.go new/glab-1.65.0/internal/commands/issue/update/issue_update_integration_test.go --- old/glab-1.64.0/internal/commands/issue/update/issue_update_integration_test.go 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/internal/commands/issue/update/issue_update_integration_test.go 2025-07-29 14:35:18.000000000 +0200 @@ -79,6 +79,16 @@ ExpectedMsg: []string{"- Updating issue #0", "error expected"}, wantErr: true, }, + { + Name: "Due date applied", + Issue: fmt.Sprintf(`-R %s/cli-automated-testing/test 1 -t "New Title" --due-date 2025-07-22`, glTestHost), + ExpectedMsg: []string{ + "- Updating issue #1", + "✓ updated title to \"New Title\"", + "✓ added due date", + "#1 New Title", + }, + }, } cfg, err := config.Init() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/internal/commands/job/artifact/artifact.go new/glab-1.65.0/internal/commands/job/artifact/artifact.go --- old/glab-1.64.0/internal/commands/job/artifact/artifact.go 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/internal/commands/job/artifact/artifact.go 2025-07-29 14:35:18.000000000 +0200 @@ -14,6 +14,7 @@ Example: heredoc.Doc(` $ glab job artifact main build $ glab job artifact main deploy --path="artifacts/" + $ glab job artifact main deploy --list-paths `), Long: ``, Args: cobra.ExactArgs(2), @@ -30,9 +31,14 @@ if err != nil { return err } - return DownloadArtifacts(apiClient, repo, path, args[0], args[1]) + listPaths, err := cmd.Flags().GetBool("list-paths") + if err != nil { + return err + } + return DownloadArtifacts(apiClient, repo, path, listPaths, args[0], args[1]) }, } jobArtifactCmd.Flags().StringP("path", "p", "./", "Path to download the artifact files.") + jobArtifactCmd.Flags().BoolP("list-paths", "l", false, "Print the paths of downloaded artifacts.") return jobArtifactCmd } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/internal/commands/job/artifact/logic.go new/glab-1.65.0/internal/commands/job/artifact/logic.go --- old/glab-1.64.0/internal/commands/job/artifact/logic.go 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/internal/commands/job/artifact/logic.go 2025-07-29 14:35:18.000000000 +0200 @@ -35,7 +35,7 @@ return nil } -func readZip(artifact *bytes.Reader, path string, zipReadLimit int64, zipFileLimit int) error { +func readZip(artifact *bytes.Reader, path string, listPaths bool, zipReadLimit int64, zipFileLimit int) error { zipReader, err := zip.NewReader(artifact, artifact.Size()) if err != nil { return err @@ -103,6 +103,10 @@ return err } + if listPaths { + fmt.Println(friendlyPath(destPath)) + } + written += writtenPerFile if written >= zipReadLimit { return fmt.Errorf("extracted zip too large: limit is %d bytes", zipReadLimit) @@ -112,11 +116,23 @@ return nil } -func DownloadArtifacts(apiClient *gitlab.Client, repo glrepo.Interface, path string, refName string, jobName string) error { +func friendlyPath(path string) string { + cwd, err := os.Getwd() + if err != nil { + return path + } + rel, err := filepath.Rel(cwd, path) + if err != nil { + return path + } + return rel +} + +func DownloadArtifacts(apiClient *gitlab.Client, repo glrepo.Interface, path string, listPaths bool, refName string, jobName string) error { artifact, _, err := apiClient.Jobs.DownloadArtifactsFile(repo.FullName(), refName, &gitlab.DownloadArtifactsFileOptions{Job: &jobName}, nil) if err != nil { return err } - return readZip(artifact, path, defaultZIPReadLimit, defaultZIPFileLimit) + return readZip(artifact, path, listPaths, defaultZIPReadLimit, defaultZIPFileLimit) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/internal/commands/job/artifact/logic_test.go new/glab-1.65.0/internal/commands/job/artifact/logic_test.go --- old/glab-1.64.0/internal/commands/job/artifact/logic_test.go 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/internal/commands/job/artifact/logic_test.go 2025-07-29 14:35:18.000000000 +0200 @@ -9,6 +9,7 @@ "testing" "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/cli/test" ) const numTestFiles = 100 @@ -78,7 +79,13 @@ require.NoError(t, err) defer os.RemoveAll(targetDir) - err = readZip(reader, targetDir, defaultZIPReadLimit, defaultZIPFileLimit) + old := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + listPaths := true + err = readZip(reader, targetDir, listPaths, defaultZIPReadLimit, defaultZIPFileLimit) + stdout := test.ReturnBuffer(old, r, w) require.NoError(t, err) files, err := listFilesInDir(targetDir) @@ -86,9 +93,11 @@ require.Len(t, files, numTestFiles) for _, file := range files { - content, err := os.ReadFile(filepath.Join(targetDir, file)) + path := filepath.Join(targetDir, file) + content, err := os.ReadFile(path) require.NoError(t, err) require.Equal(t, file, string(content)) + require.Contains(t, stdout, path) } } @@ -100,7 +109,7 @@ reader, err := toByteReader(zip.Name()) require.NoError(t, err) - err = readZip(reader, os.TempDir(), defaultZIPReadLimit, 50) + err = readZip(reader, os.TempDir(), false, defaultZIPReadLimit, 50) require.Error(t, err) require.Contains(t, err.Error(), "zip archive includes too many files") } @@ -113,7 +122,7 @@ reader, err := toByteReader(zip.Name()) require.NoError(t, err) - err = readZip(reader, os.TempDir(), 50, defaultZIPFileLimit) + err = readZip(reader, os.TempDir(), false, 50, defaultZIPFileLimit) require.Error(t, err) require.Contains(t, err.Error(), "extracted zip too large") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/internal/commands/mr/view/mr_view.go new/glab-1.65.0/internal/commands/mr/view/mr_view.go --- old/glab-1.64.0/internal/commands/mr/view/mr_view.go 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/internal/commands/mr/view/mr_view.go 2025-07-29 14:35:18.000000000 +0200 @@ -3,6 +3,7 @@ import ( "encoding/json" "fmt" + "io" "strings" "gitlab.com/gitlab-org/cli/internal/config" @@ -270,6 +271,12 @@ body, _ := utils.RenderMarkdown(note.Body, opts.io.BackgroundColor()) fmt.Fprint(out, " commented ") fmt.Fprintf(out, c.Gray("%s\n"), createdAt) + + // Display file and line context if available + if note.Position != nil { + printCommentFileContext(out, c, note.Position) + } + fmt.Fprintln(out, utils.Indent(body, " ")) } fmt.Fprintln(out) @@ -324,3 +331,42 @@ fmt.Fprintln(opts.io.StdOut, string(mrJSON)) } } + +func printCommentFileContext(out io.Writer, c *iostreams.ColorPalette, pos *gitlab.NotePosition) { + // Check for multi-line comment first + if pos.LineRange != nil && pos.LineRange.StartRange != nil && pos.LineRange.EndRange != nil { + startLine := pos.LineRange.StartRange.NewLine + endLine := pos.LineRange.EndRange.NewLine + + // Fall back to old line numbers if new ones aren't available + if startLine == 0 { + startLine = pos.LineRange.StartRange.OldLine + } + if endLine == 0 { + endLine = pos.LineRange.EndRange.OldLine + } + + // Display range if we have valid start and end lines + if startLine > 0 && endLine > 0 { + filePath := pos.NewPath + if filePath == "" { + filePath = pos.OldPath + } + if filePath != "" { + if startLine != endLine { + fmt.Fprintf(out, " on %s:%d-%d\n", c.Cyan(filePath), startLine, endLine) + } else { + fmt.Fprintf(out, " on %s:%d\n", c.Cyan(filePath), startLine) + } + return + } + } + } + + // Fall back to single-line comment + if pos.NewPath != "" && pos.NewLine > 0 { + fmt.Fprintf(out, " on %s:%d\n", c.Cyan(pos.NewPath), pos.NewLine) + } else if pos.OldPath != "" && pos.OldLine > 0 { + fmt.Fprintf(out, " on %s:%d\n", c.Cyan(pos.OldPath), pos.OldLine) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glab-1.64.0/internal/commands/mr/view/mr_view_test.go new/glab-1.65.0/internal/commands/mr/view/mr_view_test.go --- old/glab-1.64.0/internal/commands/mr/view/mr_view_test.go 2025-07-23 09:59:24.000000000 +0200 +++ new/glab-1.65.0/internal/commands/mr/view/mr_view_test.go 2025-07-29 14:35:18.000000000 +0200 @@ -27,17 +27,17 @@ ) var ( - f cmdutils.Factory - stdout *bytes.Buffer - stderr *bytes.Buffer - io *iostreams.IOStreams + f cmdutils.Factory + stdout *bytes.Buffer + stderr *bytes.Buffer + ioStreams *iostreams.IOStreams ) func TestMain(m *testing.M) { - io, _, stdout, stderr = cmdtest.TestIOStreams(cmdtest.WithTestIOStreamsAsTTY(true)) + ioStreams, _, stdout, stderr = cmdtest.TestIOStreams(cmdtest.WithTestIOStreamsAsTTY(true)) client, _ := gitlab.NewClient("") f = cmdtest.NewTestFactory( - io, + ioStreams, cmdtest.WithConfig(config.NewFromString(heredoc.Doc(` hosts: gitlab.com: @@ -181,8 +181,8 @@ }) t.Run("no_tty", func(t *testing.T) { - io.IsaTTY = false - io.IsErrTTY = false + ioStreams.IsaTTY = false + ioStreams.IsErrTTY = false cmd := NewCmdView(f) cmdutils.EnableRepoOverride(cmd, f) @@ -269,7 +269,7 @@ }, } - io, _, _, _ = cmdtest.TestIOStreams(cmdtest.WithTestIOStreamsAsTTY(true)) + ioStreams, _, _, _ = cmdtest.TestIOStreams(cmdtest.WithTestIOStreamsAsTTY(true)) tests := []struct { name string @@ -281,7 +281,7 @@ { "mr_default", &options{ - io: io, + io: ioStreams, }, mr, notes, @@ -303,7 +303,7 @@ { "mr_show_comments_no_comments", &options{ - io: io, + io: ioStreams, showComments: true, showSystemLogs: true, }, @@ -329,7 +329,7 @@ { "mr_with_comments_and_notes", &options{ - io: io, + io: ioStreams, showComments: true, showSystemLogs: true, }, @@ -504,3 +504,83 @@ assert.True(t, json.Valid([]byte(output.String()))) assert.Empty(t, output.Stderr()) } + +func TestPrintCommentFileContext(t *testing.T) { + // NOTE: we need to force disable colors, otherwise we'd need ANSI sequences in our test output assertions. + t.Setenv("NO_COLOR", "true") + + ioStr, _, _, _ := cmdtest.TestIOStreams(cmdtest.WithTestIOStreamsAsTTY(true)) + c := ioStr.Color() + + tests := []struct { + name string + note *gitlab.Note + expected string + }{ + { + name: "single line comment on new file", + note: &gitlab.Note{ + Position: &gitlab.NotePosition{ + NewPath: "internal/commands/mr/view/mr_view.go", + NewLine: 42, + }, + }, + expected: " on internal/commands/mr/view/mr_view.go:42\n", + }, + { + name: "single line comment on old file", + note: &gitlab.Note{ + Position: &gitlab.NotePosition{ + OldPath: "internal/commands/mr/view/mr_view.go", + OldLine: 35, + }, + }, + expected: " on internal/commands/mr/view/mr_view.go:35\n", + }, + { + name: "multi-line comment", + note: &gitlab.Note{ + Position: &gitlab.NotePosition{ + NewPath: "internal/gateway/mcp/tools/get_coin_open_interest.go", + LineRange: &gitlab.LineRange{ + StartRange: &gitlab.LinePosition{NewLine: 63}, + EndRange: &gitlab.LinePosition{NewLine: 68}, + }, + }, + }, + expected: " on internal/gateway/mcp/tools/get_coin_open_interest.go:63-68\n", + }, + { + name: "single line range (same start and end)", + note: &gitlab.Note{ + Position: &gitlab.NotePosition{ + NewPath: "main.go", + LineRange: &gitlab.LineRange{ + StartRange: &gitlab.LinePosition{NewLine: 10}, + EndRange: &gitlab.LinePosition{NewLine: 10}, + }, + }, + }, + expected: " on main.go:10\n", + }, + { + name: "position with no line numbers", + note: &gitlab.Note{ + Position: &gitlab.NotePosition{ + NewPath: "file.go", + NewLine: 0, + }, + }, + expected: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var buf bytes.Buffer + printCommentFileContext(&buf, c, tt.note.Position) + got := buf.String() + assert.Equal(t, tt.expected, got) + }) + } +} ++++++ glab.obsinfo ++++++ --- /var/tmp/diff_new_pack.ijJVMz/_old 2025-08-04 15:25:36.167959595 +0200 +++ /var/tmp/diff_new_pack.ijJVMz/_new 2025-08-04 15:25:36.171959762 +0200 @@ -1,5 +1,5 @@ name: glab -version: 1.64.0 -mtime: 1753257564 -commit: fe60bcf75bfb58801f5a429a52a3461ef62b0f6e +version: 1.65.0 +mtime: 1753792518 +commit: 8514bc42ef2c15a0ff27782a22b3add584b0d21c ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/glab/vendor.tar.gz /work/SRC/openSUSE:Factory/.glab.new.1085/vendor.tar.gz differ: char 16, line 1