From c4cf02616a412a84f13bfeb9ede3bece5669e3b6 Mon Sep 17 00:00:00 2001 From: Julian Zhu Date: Sat, 28 Feb 2026 18:27:56 +0800 Subject: [PATCH 1/3] Fix output format --- check_version.go | 2 +- spec.go | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/check_version.go b/check_version.go index 5619509..cb66361 100644 --- a/check_version.go +++ b/check_version.go @@ -173,7 +173,7 @@ func pkgVersionFromGit(gitdir string, u *upstream, preferredRev string, forcePre u.version = fmt.Sprintf("%s.%s+git%s", u.version, dateStr, lastCommitHash) } else { // without tag: 0.git20250101.96ee002 96ee0021ea0fb9174681b8004d8deba3c499d7f5 - u.version = fmt.Sprintf("0.git%s.%s\n%%define commit_id %s", dateStr, lastCommitHash, fullCommitHash) + u.version = fmt.Sprintf("0+git%s.%s\n%%define commit_id %s", dateStr, lastCommitHash, fullCommitHash) } return u.version, nil } diff --git a/spec.go b/spec.go index 5179687..029fef0 100644 --- a/spec.go +++ b/spec.go @@ -58,17 +58,40 @@ func writeSpec(dir, gopkg, openRuyiSrc, openRuyiLib, openRuyiProgram, version st // Macros fmt.Fprintf(f, "%%define _name %s\n", upstreamName) fmt.Fprintf(f, "%%define go_import_path %s\n", gopkg) + + // If pkgVersionFromGit embedded a commit_id define in u.version, extract and write it here + commitRe := regexp.MustCompile(`%define\s+commit_id\s+([0-9a-fA-F]+)`) + if m := commitRe.FindStringSubmatch(u.version); m != nil { + fmt.Fprintf(f, "%%define commit_id %s\n", m[1]) + // Remove the embedded %define line from version so it doesn't get written to Version: field + version = commitRe.ReplaceAllString(version, "") + version = strings.TrimSpace(version) + } fmt.Fprintf(f, "\n") // Header fmt.Fprintf(f, "Name: %s\n", openRuyiSrc) + + // Some times typeLibrary is treat as typeProgram, + // So we add an additional Name line, and keep one of those mannually + switch pkgType { + case typeProgram: + fmt.Fprintf(f, "Name: %s\n", openRuyiLib) + } + fmt.Fprintf(f, "Version: %s\n", version) fmt.Fprintf(f, "Release: %%autorelease\n") fmt.Fprintf(f, "Summary: %s\n", description) fmt.Fprintf(f, "License: %s\n", license) fmt.Fprintf(f, "URL: https://github.com/%s/%s\n", owner, repo) fmt.Fprintf(f, "#!RemoteAsset\n") - fmt.Fprintf(f, "Source0: https://github.com/%s/%s/archive/v%%{version}.tar.gz#/%%{_name}-%%{version}.tar.gz\n", owner, repo) + // If the computed version text contains a commit_id definition (see pkgVersionFromGit), + // use the commit_id tarball instead of v%{version}.tar.gz + if strings.Contains(u.version, "commit_id") { + fmt.Fprintf(f, "Source0: https://github.com/%s/%s/archive/%%{commit_id}.tar.gz#/%%{_name}-%%{version}.tar.gz\n", owner, repo) + } else { + fmt.Fprintf(f, "Source0: https://github.com/%s/%s/archive/v%%{version}.tar.gz#/%%{_name}-%%{version}.tar.gz\n", owner, repo) + } switch pkgType { case typeLibrary: @@ -125,6 +148,7 @@ func writeSpec(dir, gopkg, openRuyiSrc, openRuyiLib, openRuyiProgram, version st func writeRPMLibraryPackage(f *os.File, gopkg, openRuyiLib, longdesc string, deps []string) { fmt.Fprintf(f, "\n") fmt.Fprintf(f, "Provides: go(%s) = %%{version}\n", gopkg) + fmt.Fprintf(f, "\n") // 库包的运行时依赖 if len(deps) > 0 { for _, dep := range deps { @@ -141,10 +165,13 @@ func writeRPMLibrarySubpackage(f *os.File, gopkg, openRuyiLib, openRuyiSrc, long fmt.Fprintf(f, "Summary: Development files of %s\n", filepath.Base(gopkg)) fmt.Fprintf(f, "Provides: go(%s) = %%{version}\n", gopkg) fmt.Fprintf(f, "BuildArch: noarch\n") - for _, dep := range deps { - fmt.Fprintf(f, "Requires: %s\n", dep) + if len(deps) > 0 { + for _, dep := range deps { + fmt.Fprintf(f, "Requires: %s\n", dep) + } + } else { + fmt.Fprintf(f, "\n") } - fmt.Fprintf(f, "\n") fmt.Fprintf(f, "%%description -n %s\n", openRuyiLib) fmt.Fprintf(f, "%s\n", longdesc) fmt.Fprintf(f, "\n") -- 2.54.0 From c3045d0cfe451033e5a69b4701b68aad07848bc5 Mon Sep 17 00:00:00 2001 From: Julian Zhu Date: Tue, 14 Apr 2026 16:10:00 +0800 Subject: [PATCH 2/3] Only exit with error if folder is non-empty --- pack.go | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/pack.go b/pack.go index 5cf69a7..b70aa62 100644 --- a/pack.go +++ b/pack.go @@ -417,8 +417,14 @@ func createDirectory(openRuyiSrc string) (string, error) { return "", fmt.Errorf("get cwd: %w", err) } dir := filepath.Join(wd, openRuyiSrc) - if err := os.Mkdir(dir, 0755); err != nil { - return "", fmt.Errorf("mkdir: %w", err) + + // Try to create the directory + err = os.Mkdir(dir, 0755) + if err != nil { + // If directory already exists, that's ok (it was verified to be empty) + if !os.IsExist(err) { + return "", fmt.Errorf("mkdir: %w", err) + } } return dir, nil } @@ -663,9 +669,6 @@ func mainPack(args []string, usage func()) { if pkgType != typeGuess { openRuyiSrc = nameFromGopkg(gopkg, pkgType, customProgPkgName, allowUnknownHoster) - if _, err := os.Stat(openRuyiSrc); err == nil { - log.Fatalf("Output directory %q already exists, aborting\n", openRuyiSrc) - } } if strings.ToLower(gopkg) != gopkg { @@ -679,23 +682,7 @@ func mainPack(args []string, usage func()) { gopkg, strings.ToLower(gopkg)) } - info, err := os.Stat(openRuyiSrc) - if err == nil { - if !info.IsDir() { - log.Fatalf("%q exists but is not a directory\n", openRuyiSrc) - } - - entries, err := os.ReadDir(openRuyiSrc) - if err != nil { - log.Fatalf("Failed to read directory %q: %v\n", openRuyiSrc, err) - } - - if len(entries) != 0 { - log.Fatalf("Output directory %q exists and is non-empty, aborting\n", openRuyiSrc) - } - } else if !os.IsNotExist(err) { - log.Fatalf("Failed to stat %q: %v\n", openRuyiSrc, err) - } + // NOTE: directory existence is checked after determining final openRuyiSrc // Create a tarball of the upstream source u, err := makeUpstreamSourceTarball(gopkg, gitRevision, forcePrerelease) @@ -713,6 +700,23 @@ func mainPack(args []string, usage func()) { } } + // Now that we know the final package name, check output directory + info, err := os.Stat(openRuyiSrc) + if err == nil { + if !info.IsDir() { + log.Fatalf("%q exists but is not a directory\n", openRuyiSrc) + } + entries, err := os.ReadDir(openRuyiSrc) + if err != nil { + log.Fatalf("Failed to read directory %q: %v\n", openRuyiSrc, err) + } + if len(entries) != 0 { + log.Fatalf("Output directory %q exists and is non-empty, aborting\n", openRuyiSrc) + } + } else if !os.IsNotExist(err) { + log.Fatalf("Failed to stat %q: %v\n", openRuyiSrc, err) + } + orig := fmt.Sprintf("%s_%s.orig.tar.%s", openRuyiSrc, u.version, u.compression) log.Printf("Moving tempfile to %q\n", orig) // We need to copy the file, merely renaming is not enough since the file -- 2.54.0 From 4ba04416b43039037ffa599edbdd4ecd3833a00c Mon Sep 17 00:00:00 2001 From: Julian Zhu Date: Tue, 14 Apr 2026 16:16:05 +0800 Subject: [PATCH 3/3] Use GITHUB_TOKEN to access GitHub and avoid access limit Attempt to get GITHUB_TOKEN from environment variables, to avoid GitHub access limit --- main.go | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/main.go b/main.go index 8f42506..7aad5ed 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "net/http" "os" "github.com/google/go-github/v60/github" @@ -11,6 +12,17 @@ var ( gitHub *github.Client ) +// TokenTransport implements http.RoundTripper for Bearer token authentication +type TokenTransport struct { + Token string + Transport http.RoundTripper +} + +func (t *TokenTransport) RoundTrip(req *http.Request) (*http.Response, error) { + req.Header.Add("Authorization", "Bearer "+t.Token) + return t.Transport.RoundTrip(req) +} + func printHelp() { helpText := `go2spec - A tool to package Go modules into RPM spec files. @@ -29,13 +41,28 @@ If there are no commands provided, the tool will default to executing the 'pack' } func main() { - transport := github.BasicAuthTransport{ - Username: os.Getenv("GITHUB_USERNAME"), - Password: os.Getenv("GITHUB_PASSWORD"), - OTP: os.Getenv("GITHUB_OTP"), - Transport: httpcache.NewMemoryCacheTransport(), + token := os.Getenv("GITHUB_TOKEN") + + var client *http.Client + if token != "" { + // Use token authentication for better rate limits + client = &http.Client{ + Transport: &TokenTransport{ + Token: token, + Transport: httpcache.NewMemoryCacheTransport(), + }, + } + } else { + // Fallback to basic auth if token is not provided + transport := github.BasicAuthTransport{ + Username: os.Getenv("GITHUB_USERNAME"), + Password: os.Getenv("GITHUB_PASSWORD"), + OTP: os.Getenv("GITHUB_OTP"), + Transport: httpcache.NewMemoryCacheTransport(), + } + client = transport.Client() } - gitHub = github.NewClient(transport.Client()) + gitHub = github.NewClient(client) args := os.Args[1:] -- 2.54.0