Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package git-credential-oauth for
openSUSE:Factory checked in at 2026-01-26 11:02:46
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/git-credential-oauth (Old)
and /work/SRC/openSUSE:Factory/.git-credential-oauth.new.1928 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "git-credential-oauth"
Mon Jan 26 11:02:46 2026 rev:7 rq:1328970 version:0.17.2
Changes:
--------
---
/work/SRC/openSUSE:Factory/git-credential-oauth/git-credential-oauth.changes
2025-03-02 12:21:26.951557782 +0100
+++
/work/SRC/openSUSE:Factory/.git-credential-oauth.new.1928/git-credential-oauth.changes
2026-01-26 11:03:19.784521444 +0100
@@ -1,0 +2,16 @@
+Fri Jan 23 16:57:59 UTC 2026 - [email protected]
+
+- Update to version 0.17.2:
+ * Recognise Forgejo
+ * Recognise gitea subdomain (gitea.example.com)
+- Update to version 0.17.1:
+ * Fix device configure
+- Update to version 0.17.0:
+ * Added support for GitHub Gists
+ * Display QR code for authentication
+- Update to version 0.16.0:
+ * Support dark mode in HTML page
+- Update to version 0.15.1:
+ * Drop go-cmp dependency
+
+-------------------------------------------------------------------
Old:
----
git-credential-oauth-0.15.0.tar.gz
New:
----
git-credential-oauth-0.17.2.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ git-credential-oauth.spec ++++++
--- /var/tmp/diff_new_pack.YRW312/_old 2026-01-26 11:03:21.272583764 +0100
+++ /var/tmp/diff_new_pack.YRW312/_new 2026-01-26 11:03:21.280584099 +0100
@@ -1,7 +1,7 @@
#
# spec file for package git-credential-oauth
#
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
Name: git-credential-oauth
-Version: 0.15.0
+Version: 0.17.2
Release: 0
Summary: Git credential helper that authenticates to GitHub and other
forges using OAuth
License: Apache-2.0
@@ -27,7 +27,7 @@
Source1: vendor.tar.zst
BuildRequires: golang-packaging
BuildRequires: zstd
-BuildRequires: golang(API)
+BuildRequires: golang(API) >= 1.24.1
Requires: git-core
%description
++++++ git-credential-oauth-0.15.0.tar.gz -> git-credential-oauth-0.17.2.tar.gz
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/git-credential-oauth-0.15.0/.goreleaser.yaml
new/git-credential-oauth-0.17.2/.goreleaser.yaml
--- old/git-credential-oauth-0.15.0/.goreleaser.yaml 2025-03-01
01:11:25.000000000 +0100
+++ new/git-credential-oauth-0.17.2/.goreleaser.yaml 2026-01-14
11:16:38.000000000 +0100
@@ -1,3 +1,4 @@
+version: 2
before:
hooks:
- go mod tidy
@@ -8,7 +9,7 @@
-
format_overrides:
- goos: windows
- format: zip
+ formats: zip
# modelines, feel free to remove those if you don't want/use them:
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/git-credential-oauth-0.15.0/README.md
new/git-credential-oauth-0.17.2/README.md
--- old/git-credential-oauth-0.15.0/README.md 2025-03-01 01:11:25.000000000
+0100
+++ new/git-credential-oauth-0.17.2/README.md 2026-01-14 11:16:38.000000000
+0100
@@ -35,7 +35,7 @@
| gitlab.com | ✔ | ✔ | ✔ |
| gitlab.example.com |
[🗙](https://gitlab.com/gitlab-org/gitlab/-/issues/374172) | ✔
| ✔ |
| gitea.example.com | ✔ | ✔ |
[🗙](https://github.com/go-gitea/gitea/issues/27309) |
-| forgejo.example.com | ✔ | ✔ | 🗙 |
+| forgejo.example.com | ✔ | ✔ |
[🗙](https://codeberg.org/forgejo/forgejo/issues/4830) |
| bitbucket.org | ✔ | ✔ | 🗙 |
| googlesource.com | ✔ | ✔ |
[🗙](https://github.com/hickford/git-credential-oauth/issues/38) |
@@ -180,7 +180,7 @@
```sh
git config --global credential.https://code.example.com.oauthClientId
<CLIENTID>
git config --global credential.https://code.example.com.oauthScopes
"read_repository write_repository"
-git config --global credential.https://code.example.com.oauthAuthURL
/oauth/authorize>
+git config --global credential.https://code.example.com.oauthAuthURL
/oauth/authorize
git config --global credential.https://code.example.com.oauthTokenURL
/oauth/token
git config --global credential.https://code.example.com.oauthDeviceAuthURL
/oauth/authorize_device
```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/git-credential-oauth-0.15.0/go.mod
new/git-credential-oauth-0.17.2/go.mod
--- old/git-credential-oauth-0.15.0/go.mod 2025-03-01 01:11:25.000000000
+0100
+++ new/git-credential-oauth-0.17.2/go.mod 2026-01-14 11:16:38.000000000
+0100
@@ -1,5 +1,9 @@
module github.com/hickford/git-credential-oauth
-go 1.22.2
+go 1.23.0
-require golang.org/x/oauth2 v0.23.0
+toolchain go1.24.1
+
+require golang.org/x/oauth2 v0.30.0
+
+require rsc.io/qr v0.2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/git-credential-oauth-0.15.0/go.sum
new/git-credential-oauth-0.17.2/go.sum
--- old/git-credential-oauth-0.15.0/go.sum 2025-03-01 01:11:25.000000000
+0100
+++ new/git-credential-oauth-0.17.2/go.sum 2026-01-14 11:16:38.000000000
+0100
@@ -1,4 +1,4 @@
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
-github.com/google/go-cmp v0.5.9/go.mod
h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
-golang.org/x/oauth2 v0.23.0/go.mod
h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
+golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
+golang.org/x/oauth2 v0.30.0/go.mod
h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
+rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY=
+rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/git-credential-oauth-0.15.0/main.go
new/git-credential-oauth-0.17.2/main.go
--- old/git-credential-oauth-0.15.0/main.go 2025-03-01 01:11:25.000000000
+0100
+++ new/git-credential-oauth-0.17.2/main.go 2026-01-14 11:16:38.000000000
+0100
@@ -14,6 +14,7 @@
package main
import (
+ "bytes"
"context"
"flag"
"fmt"
@@ -31,6 +32,7 @@
"golang.org/x/oauth2"
"golang.org/x/oauth2/endpoints"
+ "rsc.io/qr"
)
// configByHost lists default config for several public hosts.
@@ -46,6 +48,11 @@
ClientSecret: "2b746eea028711749c5062b9fe626fed78d03cc0",
Endpoint: endpoints.GitHub,
Scopes: []string{"repo", "gist", "workflow"}},
+ "gist.github.com": {
+ ClientID: "b895675a4e2cf54d5c6c",
+ ClientSecret: "2b746eea028711749c5062b9fe626fed78d03cc0",
+ Endpoint: endpoints.GitHub,
+ Scopes: []string{"repo", "gist", "workflow"}},
// https://gitlab.com/oauth/applications/232663
"gitlab.com": {
ClientID:
"10bfbbf46e5b760b55ce772a262d7a0205eacc417816eb84d37d0fb02c89bb97",
@@ -131,13 +138,11 @@
func parse(input string) map[string]string {
lines := strings.Split(string(input), "\n")
- pairs := map[string]string{}
+ pairs := make(map[string]string, len(lines))
for _, line := range lines {
- parts := strings.SplitN(line, "=", 2)
- if len(parts) >= 2 {
- key, value := parts[0], parts[1]
+ if key, value, ok := strings.Cut(line, "="); ok {
_, exists := pairs[key]
- if strings.HasSuffix(key, "[]") && exists {
+ if exists && strings.HasSuffix(key, "[]") {
pairs[key] += "\n" + value
} else {
pairs[key] = value
@@ -198,7 +203,8 @@
}
host := pairs["host"]
looksLikeGitLab := strings.HasPrefix(host, "gitlab.") ||
strings.Contains(pairs["wwwauth[]"], `realm="GitLab"`)
- looksLikeGitea := strings.Contains(pairs["wwwauth[]"],
`realm="Gitea"`)
+ looksLikeGitea := strings.HasPrefix(host, "gitea.") ||
strings.Contains(pairs["wwwauth[]"], `realm="Gitea"`)
+ looksLikeForgejo := strings.HasPrefix(host, "forgejo.") ||
strings.Contains(pairs["wwwauth[]"], `realm="Forgejo"`)
looksLikeGitHub := strings.HasPrefix(host, "github.") ||
strings.Contains(pairs["wwwauth[]"], `realm="GitHub"`)
urll := fmt.Sprintf("%s://%s", pairs["protocol"], host)
c, found := configByHost[host]
@@ -218,7 +224,7 @@
}
c.Scopes = configByHost["gitlab.com"].Scopes
}
- if !found && looksLikeGitea {
+ if !found && (looksLikeGitea || looksLikeForgejo) {
c.ClientID = "a4792ccc-144e-407e-86c9-5e7d8d9c3269"
c.Endpoint = oauth2.Endpoint{
AuthURL:
fmt.Sprintf("%s/login/oauth/authorize", urll),
@@ -301,9 +307,15 @@
}
var authURLSuffix string
- if looksLikeGitHub && pairs["username"] != "" &&
pairs["username"] != "oauth2" {
- //
https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#1-request-a-users-github-identity
- authURLSuffix = fmt.Sprintf("&login=%s",
pairs["username"])
+ if pairs["username"] != "" && pairs["username"] != "oauth2" {
+ if looksLikeGitHub {
+ //
https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#1-request-a-users-github-identity
+ authURLSuffix = fmt.Sprintf("&login=%s",
pairs["username"])
+ }
+ if strings.HasSuffix(host, ".googlesource.com") {
+ //
https://developers.google.com/identity/protocols/oauth2/web-server#creatingclient
+ authURLSuffix = fmt.Sprintf("&login_hint=%s",
pairs["username"])
+ }
}
if token == nil {
@@ -322,7 +334,7 @@
}
// "A capability[] directive must precede any value depending
on it and these directives should be the first item announced in the protocol."
https://git-scm.com/docs/git-credential
fmt.Println("capability[]=authtype")
- output := map[string]string{}
+ output := make(map[string]string, 5)
hostSupportsBearer := host == "bitbucket.org" || host ==
"codeberg.org" || host == "gitea.com" || looksLikeGitea ||
strings.HasSuffix(host, ".googlesource.com")
authtypeCapable := strings.Contains(pairs["capability[]"],
"authtype")
if bearer && hostSupportsBearer && authtypeCapable {
@@ -369,11 +381,17 @@
// six hours
storage = "cache --timeout 21600"
}
+ helper := "oauth"
+ if device {
+ helper += " -device"
+ }
commands = []*exec.Cmd{exec.Command(gitPath, "config",
"--global", "--unset-all", "credential.helper"),
exec.Command(gitPath, "config", "--global",
"--add", "credential.helper", storage),
- exec.Command(gitPath, "config", "--global",
"--add", "credential.helper", "oauth")}
+ exec.Command(gitPath, "config", "--global",
"--add", "credential.helper", helper),
+ }
} else if args[0] == "unconfigure" {
- commands = []*exec.Cmd{exec.Command(gitPath, "config",
"--global", "--unset-all", "credential.helper", "oauth")}
+ commands = []*exec.Cmd{
+ exec.Command(gitPath, "config", "--global",
"--unset-all", "credential.helper", "oauth*")}
}
for _, cmd := range commands {
cmd.Stderr = os.Stderr
@@ -397,10 +415,11 @@
}
}
-var template string = `<!DOCTYPE html>
+const template string = `<!DOCTYPE html>
<html lang="en">
<head>
<title>Git authentication</title>
+ <meta name="color-scheme" content="light dark" />
</head>
<body>
<p>Success. You may close this page and return to Git.</p>
@@ -487,15 +506,54 @@
func getDeviceToken(ctx context.Context, c oauth2.Config) (*oauth2.Token,
error) {
deviceAuth, err := c.DeviceAuth(ctx)
if err != nil {
- log.Fatalln(err)
+ return nil, err
}
if verbose {
fmt.Fprintf(os.Stderr, "%+v\n", deviceAuth)
}
- fmt.Fprintf(os.Stderr, "Please enter code %s at %s\n",
deviceAuth.UserCode, deviceAuth.VerificationURI)
+ if deviceAuth.VerificationURIComplete != "" {
+ fmt.Fprintf(os.Stderr, "Please scan the QR code or enter code
%s at %s\n", deviceAuth.UserCode, deviceAuth.VerificationURI)
+ fmt.Fprintln(os.Stderr)
+ writeQRCode(os.Stderr, deviceAuth.VerificationURIComplete)
+ } else {
+ fmt.Fprintf(os.Stderr, "Please enter code %s at %s\n",
deviceAuth.UserCode, deviceAuth.VerificationURI)
+ }
return c.DeviceAccessToken(ctx, deviceAuth)
}
+func writeQRCode(w io.Writer, data string) error {
+ // use low redundancy to generate small QR codes for terminal output.
+ // we assume the user is sitting in front of their screen so image
quality shouldn't be an issue
+ code, err := qr.Encode(data, qr.L)
+ if err != nil {
+ return err
+ }
+
+ var (
+ black = "\033[40m \033[0m"
+ white = "\033[107m \033[0m"
+ whiteLine = strings.Repeat(white, code.Size+2) + "\n"
+ buf bytes.Buffer
+ )
+ buf.WriteString(whiteLine)
+ for y := range code.Size {
+ buf.WriteString(white)
+ for x := range code.Size {
+ if code.Black(x, y) {
+ buf.WriteString(black)
+ } else {
+ buf.WriteString(white)
+ }
+ }
+ buf.WriteString(white)
+ buf.WriteRune('\n')
+ }
+ buf.WriteString(whiteLine)
+
+ _, err = buf.WriteTo(w)
+ return err
+}
+
func replaceHost(e oauth2.Endpoint, host string) oauth2.Endpoint {
e.AuthURL = replaceHostInURL(e.AuthURL, host)
e.TokenURL = replaceHostInURL(e.TokenURL, host)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/git-credential-oauth-0.15.0/main_test.go
new/git-credential-oauth-0.17.2/main_test.go
--- old/git-credential-oauth-0.15.0/main_test.go 2025-03-01
01:11:25.000000000 +0100
+++ new/git-credential-oauth-0.17.2/main_test.go 2026-01-14
11:16:38.000000000 +0100
@@ -1,13 +1,14 @@
package main
import (
+ "os"
"strings"
"testing"
)
func TestConfig(t *testing.T) {
for key, c := range configByHost {
- if key == "android.googlesource.com" {
+ if key == "android.googlesource.com" || key ==
"gist.github.com" {
continue
}
if !strings.Contains(c.Endpoint.AuthURL, key) {
@@ -22,6 +23,16 @@
}
}
+func TestQR(t *testing.T) {
+ msg := os.Getenv("QR_MSG")
+ if msg == "" {
+ t.Skip("no QR_MSG set, skipping")
+ }
+ if err := writeQRCode(os.Stdout, msg); err != nil {
+ t.Fatal(err)
+ }
+}
+
func FuzzParse(f *testing.F) {
f.Add("key=value")
f.Add("key=")
++++++ vendor.tar.zst ++++++
++++ 2549 lines of diff (skipped)