From bf17cc6c693d8090bcb3c4ffbf8d067acadb1edf Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 22:08:54 -0500 Subject: [PATCH] Replace github.com/unknwon/com with stdlib and internal helpers (#8148) Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Joe Chen Co-authored-by: Claude Opus 4.6 --- cmd/gogs/hook.go | 16 +++--- cmd/gogs/import.go | 8 +-- cmd/gogs/serv.go | 5 +- cmd/gogs/web.go | 3 +- internal/context/notice.go | 4 +- internal/database/comment.go | 6 +-- internal/database/issue.go | 9 ++-- internal/database/issue_mail.go | 8 +-- internal/database/mirror.go | 5 +- internal/database/pull.go | 15 +++--- internal/database/repo.go | 62 +++++++++++++----------- internal/database/repo_branch.go | 4 +- internal/database/repo_editor.go | 27 ++++++----- internal/database/ssh_key.go | 8 +-- internal/database/two_factor.go | 3 +- internal/database/wiki.go | 17 ++++--- internal/form/repo.go | 4 +- internal/ioutil/ioutil.go | 47 ++++++++++++++++++ internal/markup/markup.go | 8 +-- internal/route/admin/auths.go | 4 +- internal/route/admin/notice.go | 4 +- internal/route/api/v1/convert/convert.go | 7 ++- internal/route/api/v1/repo/hook.go | 34 ++++++------- internal/route/api/v1/repo/label.go | 4 +- internal/route/install.go | 22 ++++----- internal/route/org/members.go | 5 +- internal/route/org/teams.go | 7 +-- internal/route/repo/issue.go | 7 +-- internal/route/repo/pull.go | 6 +-- internal/route/repo/repo.go | 6 +-- internal/route/repo/setting.go | 3 +- internal/route/user/auth.go | 6 +-- internal/route/user/home.go | 4 +- internal/ssh/ssh.go | 6 +-- internal/strutil/strutil.go | 11 +++++ internal/strutil/strutil_test.go | 12 +++++ internal/sync/unique_queue.go | 8 +-- internal/tool/tool.go | 15 +++--- 38 files changed, 259 insertions(+), 171 deletions(-) create mode 100644 internal/ioutil/ioutil.go diff --git a/cmd/gogs/hook.go b/cmd/gogs/hook.go index 248a3bad9..24f8aea20 100644 --- a/cmd/gogs/hook.go +++ b/cmd/gogs/hook.go @@ -9,9 +9,9 @@ import ( "os" "os/exec" "path/filepath" + "strconv" "strings" - "github.com/unknwon/com" "github.com/urfave/cli" log "unknwon.dev/clog/v2" @@ -21,6 +21,7 @@ import ( "gogs.io/gogs/internal/database" "gogs.io/gogs/internal/email" "gogs.io/gogs/internal/httplib" + "gogs.io/gogs/internal/osutil" ) var ( @@ -85,7 +86,7 @@ func runHookPreReceive(c *cli.Context) error { branchName := git.RefShortName(string(fields[2])) // Branch protection - repoID := com.StrTo(os.Getenv(database.EnvRepoID)).MustInt64() + repoID, _ := strconv.ParseInt(os.Getenv(database.EnvRepoID), 10, 64) protectBranch, err := database.GetProtectBranchOfRepoByName(repoID, branchName) if err != nil { if database.IsErrBranchNotExist(err) { @@ -101,7 +102,7 @@ func runHookPreReceive(c *cli.Context) error { bypassRequirePullRequest := false // Check if user is in whitelist when enabled - userID := com.StrTo(os.Getenv(database.EnvAuthUserID)).MustInt64() + userID, _ := strconv.ParseInt(os.Getenv(database.EnvAuthUserID), 10, 64) if protectBranch.EnableWhitelist { if !database.IsUserInProtectBranchWhitelist(repoID, userID, branchName) { fail(fmt.Sprintf("Branch '%s' is protected and you are not in the push whitelist", branchName), "") @@ -131,7 +132,7 @@ func runHookPreReceive(c *cli.Context) error { } customHooksPath := filepath.Join(os.Getenv(database.EnvRepoCustomHooksPath), "pre-receive") - if !com.IsFile(customHooksPath) { + if !osutil.IsFile(customHooksPath) { return nil } @@ -165,7 +166,7 @@ func runHookUpdate(c *cli.Context) error { } customHooksPath := filepath.Join(os.Getenv(database.EnvRepoCustomHooksPath), "update") - if !com.IsFile(customHooksPath) { + if !osutil.IsFile(customHooksPath) { return nil } @@ -213,11 +214,12 @@ func runHookPostReceive(c *cli.Context) error { continue } + pusherID, _ := strconv.ParseInt(os.Getenv(database.EnvAuthUserID), 10, 64) options := database.PushUpdateOptions{ OldCommitID: string(fields[0]), NewCommitID: string(fields[1]), FullRefspec: string(fields[2]), - PusherID: com.StrTo(os.Getenv(database.EnvAuthUserID)).MustInt64(), + PusherID: pusherID, PusherName: os.Getenv(database.EnvAuthUserName), RepoUserName: os.Getenv(database.EnvRepoOwnerName), RepoName: os.Getenv(database.EnvRepoName), @@ -249,7 +251,7 @@ func runHookPostReceive(c *cli.Context) error { } customHooksPath := filepath.Join(os.Getenv(database.EnvRepoCustomHooksPath), "post-receive") - if !com.IsFile(customHooksPath) { + if !osutil.IsFile(customHooksPath) { return nil } diff --git a/cmd/gogs/import.go b/cmd/gogs/import.go index ef01609cf..33c916583 100644 --- a/cmd/gogs/import.go +++ b/cmd/gogs/import.go @@ -9,10 +9,10 @@ import ( "time" "github.com/cockroachdb/errors" - "github.com/unknwon/com" "github.com/urfave/cli" "gogs.io/gogs/internal/conf" + "gogs.io/gogs/internal/osutil" ) var ( @@ -44,9 +44,9 @@ func runImportLocale(c *cli.Context) error { } else if !c.IsSet("target") { return errors.New("target directory is not specified") } - if !com.IsDir(c.String("source")) { + if !osutil.IsDir(c.String("source")) { return errors.Newf("source directory %q does not exist or is not a directory", c.String("source")) - } else if !com.IsDir(c.String("target")) { + } else if !osutil.IsDir(c.String("target")) { return errors.Newf("target directory %q does not exist or is not a directory", c.String("target")) } @@ -66,7 +66,7 @@ func runImportLocale(c *cli.Context) error { name := fmt.Sprintf("locale_%s.ini", lang) source := filepath.Join(c.String("source"), name) target := filepath.Join(c.String("target"), name) - if !com.IsFile(source) { + if !osutil.IsFile(source) { continue } diff --git a/cmd/gogs/serv.go b/cmd/gogs/serv.go index 104960008..7630242ac 100644 --- a/cmd/gogs/serv.go +++ b/cmd/gogs/serv.go @@ -6,10 +6,10 @@ import ( "os" "os/exec" "path/filepath" + "strconv" "strings" "time" - "github.com/unknwon/com" "github.com/urfave/cli" log "unknwon.dev/clog/v2" @@ -188,7 +188,8 @@ func runServ(c *cli.Context) error { // Allow anonymous (user is nil) clone for public repositories. var user *database.User - key, err := database.GetPublicKeyByID(com.StrTo(strings.TrimPrefix(c.Args()[0], "key-")).MustInt64()) + keyID, _ := strconv.ParseInt(strings.TrimPrefix(c.Args()[0], "key-"), 10, 64) + key, err := database.GetPublicKeyByID(keyID) if err != nil { fail("Invalid key ID", "Invalid key ID '%s': %v", c.Args()[0], err) } diff --git a/cmd/gogs/web.go b/cmd/gogs/web.go index 558d3c1f3..b19361995 100644 --- a/cmd/gogs/web.go +++ b/cmd/gogs/web.go @@ -20,7 +20,6 @@ import ( "github.com/go-macaron/session" "github.com/go-macaron/toolbox" "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/unknwon/com" "github.com/urfave/cli" "gopkg.in/macaron.v1" log "unknwon.dev/clog/v2" @@ -308,7 +307,7 @@ func runWeb(c *cli.Context) error { if err != nil { c.NotFoundOrError(err, "get attachment by UUID") return - } else if !com.IsFile(attach.LocalPath()) { + } else if !osutil.IsFile(attach.LocalPath()) { c.NotFound() return } diff --git a/internal/context/notice.go b/internal/context/notice.go index f276462f2..68a3ce341 100644 --- a/internal/context/notice.go +++ b/internal/context/notice.go @@ -4,11 +4,11 @@ import ( "os" "path/filepath" - "github.com/unknwon/com" log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/markup" + "gogs.io/gogs/internal/osutil" "gogs.io/gogs/internal/tool" ) @@ -16,7 +16,7 @@ import ( // on all pages. func (c *Context) renderNoticeBanner() { fpath := filepath.Join(conf.CustomDir(), "notice", "banner.md") - if !com.IsExist(fpath) { + if !osutil.Exist(fpath) { return } diff --git a/internal/database/comment.go b/internal/database/comment.go index f0155c849..5e29fa48b 100644 --- a/internal/database/comment.go +++ b/internal/database/comment.go @@ -3,11 +3,11 @@ package database import ( "context" "fmt" + "strconv" "strings" "time" "github.com/cockroachdb/errors" - "github.com/unknwon/com" log "unknwon.dev/clog/v2" "xorm.io/xorm" @@ -148,7 +148,7 @@ func (c *Comment) APIFormat() *api.Comment { } func CommentHashTag(id int64) string { - return "issuecomment-" + com.ToStr(id) + return "issuecomment-" + strconv.FormatInt(id, 10) } // HashTag returns unique hash tag for comment. @@ -158,7 +158,7 @@ func (c *Comment) HashTag() string { // EventTag returns unique event hash tag for comment. func (c *Comment) EventTag() string { - return "event-" + com.ToStr(c.ID) + return "event-" + strconv.FormatInt(c.ID, 10) } // mailParticipants sends new comment emails to repository watchers diff --git a/internal/database/issue.go b/internal/database/issue.go index 6746934f6..bbdbb7583 100644 --- a/internal/database/issue.go +++ b/internal/database/issue.go @@ -3,11 +3,11 @@ package database import ( "context" "fmt" + "strconv" "strings" "time" "github.com/cockroachdb/errors" - "github.com/unknwon/com" log "unknwon.dev/clog/v2" "xorm.io/xorm" @@ -221,7 +221,7 @@ func (issue *Issue) APIFormat() *api.Issue { // HashTag returns unique hash tag for issue. func (issue *Issue) HashTag() string { - return "issue-" + com.ToStr(issue.ID) + return "issue-" + strconv.FormatInt(issue.ID, 10) } // IsPoster returns true if given user by ID is the poster. @@ -828,7 +828,7 @@ func GetIssueByRef(ref string) (*Issue, error) { return nil, ErrIssueNotExist{args: map[string]any{"ref": ref}} } - index := com.StrTo(after).MustInt64() + index, _ := strconv.ParseInt(after, 10, 64) if index == 0 { return nil, ErrIssueNotExist{args: map[string]any{"ref": ref}} } @@ -1219,7 +1219,8 @@ func parseCountResult(results []map[string][]byte) int64 { return 0 } for _, result := range results[0] { - return com.StrTo(string(result)).MustInt64() + count, _ := strconv.ParseInt(string(result), 10, 64) + return count } return 0 } diff --git a/internal/database/issue_mail.go b/internal/database/issue_mail.go index 74f3507df..411c678cc 100644 --- a/internal/database/issue_mail.go +++ b/internal/database/issue_mail.go @@ -5,12 +5,12 @@ import ( "fmt" "github.com/cockroachdb/errors" - "github.com/unknwon/com" log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/email" "gogs.io/gogs/internal/markup" + "gogs.io/gogs/internal/strutil" "gogs.io/gogs/internal/userutil" ) @@ -138,7 +138,7 @@ func mailIssueCommentToParticipants(issue *Issue, doer *User, mentions []string) for i := range participants { if participants[i].ID == doer.ID { continue - } else if com.IsSliceContainsStr(names, participants[i].Name) { + } else if strutil.ContainsFold(names, participants[i].Name) { continue } @@ -146,7 +146,7 @@ func mailIssueCommentToParticipants(issue *Issue, doer *User, mentions []string) names = append(names, participants[i].Name) } if issue.Assignee != nil && issue.Assignee.ID != doer.ID { - if !com.IsSliceContainsStr(names, issue.Assignee.Name) { + if !strutil.ContainsFold(names, issue.Assignee.Name) { tos = append(tos, issue.Assignee.Email) names = append(names, issue.Assignee.Name) } @@ -157,7 +157,7 @@ func mailIssueCommentToParticipants(issue *Issue, doer *User, mentions []string) names = append(names, doer.Name) toUsernames := make([]string, 0, len(mentions)) // list of user names. for i := range mentions { - if com.IsSliceContainsStr(names, mentions[i]) { + if strutil.ContainsFold(names, mentions[i]) { continue } diff --git a/internal/database/mirror.go b/internal/database/mirror.go index 884de6ff3..0064f1efc 100644 --- a/internal/database/mirror.go +++ b/internal/database/mirror.go @@ -4,11 +4,11 @@ import ( "context" "fmt" "net/url" + "strconv" "strings" "time" "github.com/cockroachdb/errors" - "github.com/unknwon/com" "gopkg.in/ini.v1" log "unknwon.dev/clog/v2" "xorm.io/xorm" @@ -341,7 +341,8 @@ func SyncMirrors() { log.Trace("SyncMirrors [repo_id: %s]", repoID) MirrorQueue.Remove(repoID) - m, err := GetMirrorByRepoID(com.StrTo(repoID).MustInt64()) + id, _ := strconv.ParseInt(repoID, 10, 64) + m, err := GetMirrorByRepoID(id) if err != nil { log.Error("GetMirrorByRepoID [%v]: %v", repoID, err) continue diff --git a/internal/database/pull.go b/internal/database/pull.go index 90a32e052..1d17b1114 100644 --- a/internal/database/pull.go +++ b/internal/database/pull.go @@ -5,10 +5,10 @@ import ( "fmt" "os" "path/filepath" + "strconv" "time" "github.com/cockroachdb/errors" - "github.com/unknwon/com" log "unknwon.dev/clog/v2" "xorm.io/xorm" @@ -217,7 +217,7 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle // Create temporary directory to store temporary copy of the base repository, // and clean it up when operation finished regardless of succeed or not. - tmpBasePath := filepath.Join(conf.Server.AppDataPath, "tmp", "repos", com.ToStr(time.Now().Nanosecond())+".git") + tmpBasePath := filepath.Join(conf.Server.AppDataPath, "tmp", "repos", strconv.Itoa(time.Now().Nanosecond())+".git") if err = os.MkdirAll(filepath.Dir(tmpBasePath), os.ModePerm); err != nil { return err } @@ -284,7 +284,7 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle } // Name non-branch commit state to a new temporary branch in order to save changes. - tmpBranch := com.ToStr(time.Now().UnixNano(), 10) + tmpBranch := strconv.FormatInt(time.Now().UnixNano(), 10) if _, stderr, err = process.ExecDir(-1, tmpBasePath, fmt.Sprintf("PullRequest.Merge (git checkout): %s", tmpBasePath), "git", "checkout", "-b", tmpBranch); err != nil { @@ -414,8 +414,8 @@ func (pr *PullRequest) testPatch() (err error) { return nil } - repoWorkingPool.CheckIn(com.ToStr(pr.BaseRepoID)) - defer repoWorkingPool.CheckOut(com.ToStr(pr.BaseRepoID)) + repoWorkingPool.CheckIn(strconv.FormatInt(pr.BaseRepoID, 10)) + defer repoWorkingPool.CheckOut(strconv.FormatInt(pr.BaseRepoID, 10)) log.Trace("PullRequest[%d].testPatch (patchPath): %s", pr.ID, patchPath) @@ -625,7 +625,7 @@ func (pr *PullRequest) UpdatePatch() (err error) { } // Add a temporary remote. - tmpRemote := com.ToStr(time.Now().UnixNano()) + tmpRemote := strconv.FormatInt(time.Now().UnixNano(), 10) baseRepoPath := RepoPath(pr.BaseRepo.MustOwner().Name, pr.BaseRepo.Name) err = headGitRepo.RemoteAdd(tmpRemote, baseRepoPath, git.RemoteAddOptions{Fetch: true}) if err != nil { @@ -868,7 +868,8 @@ func TestPullRequests() { log.Trace("TestPullRequests[%v]: processing test task", prID) PullRequestQueue.Remove(prID) - pr, err := GetPullRequestByID(com.StrTo(prID).MustInt64()) + id, _ := strconv.ParseInt(prID, 10, 64) + pr, err := GetPullRequestByID(id) if err != nil { log.Error("GetPullRequestByID[%s]: %v", prID, err) continue diff --git a/internal/database/repo.go b/internal/database/repo.go index c8e21f85a..6d46ade28 100644 --- a/internal/database/repo.go +++ b/internal/database/repo.go @@ -11,7 +11,9 @@ import ( "os/exec" "path" "path/filepath" + "slices" "sort" + "strconv" "strings" "time" @@ -36,6 +38,7 @@ import ( "gogs.io/gogs/internal/process" "gogs.io/gogs/internal/repoutil" "gogs.io/gogs/internal/semverutil" + "gogs.io/gogs/internal/strutil" "gogs.io/gogs/internal/sync" ) @@ -77,14 +80,15 @@ func LoadRepoConfig() { } customPath := filepath.Join(conf.CustomDir(), "conf", t) - if com.IsDir(customPath) { - customFiles, err := com.StatDir(customPath) + if osutil.IsDir(customPath) { + entries, err := os.ReadDir(customPath) if err != nil { log.Fatal("Failed to get custom %s files: %v", t, err) } - for _, f := range customFiles { - if !com.IsSliceContainsStr(files, f) { + for _, entry := range entries { + f := entry.Name() + if !strutil.ContainsFold(files, f) { files = append(files, f) } } @@ -104,12 +108,12 @@ func LoadRepoConfig() { // Filter out invalid names and promote preferred licenses. sortedLicenses := make([]string, 0, len(Licenses)) for _, name := range conf.Repository.PreferredLicenses { - if com.IsSliceContainsStr(Licenses, name) { + if slices.Contains(Licenses, name) { sortedLicenses = append(sortedLicenses, name) } } for _, name := range Licenses { - if !com.IsSliceContainsStr(conf.Repository.PreferredLicenses, name) { + if !slices.Contains(conf.Repository.PreferredLicenses, name) { sortedLicenses = append(sortedLicenses, name) } } @@ -309,7 +313,7 @@ func (r *Repository) HTMLURL() string { // CustomAvatarPath returns repository custom avatar file path. func (r *Repository) CustomAvatarPath() string { - return filepath.Join(conf.Picture.RepositoryAvatarUploadPath, com.ToStr(r.ID)) + return filepath.Join(conf.Picture.RepositoryAvatarUploadPath, strconv.FormatInt(r.ID, 10)) } // RelAvatarLink returns relative avatar link to the site domain, @@ -317,7 +321,7 @@ func (r *Repository) CustomAvatarPath() string { // Since Gravatar support not needed here - just check for image path. func (r *Repository) RelAvatarLink() string { defaultImgURL := "" - if !com.IsExist(r.CustomAvatarPath()) { + if !osutil.Exist(r.CustomAvatarPath()) { return defaultImgURL } return fmt.Sprintf("%s/%s/%d", conf.Server.Subpath, RepoAvatarURLPrefix, r.ID) @@ -645,7 +649,7 @@ func (r *Repository) NextIssueIndex() int64 { } func (r *Repository) LocalCopyPath() string { - return filepath.Join(conf.Server.AppDataPath, "tmp", "local-r", com.ToStr(r.ID)) + return filepath.Join(conf.Server.AppDataPath, "tmp", "local-r", strconv.FormatInt(r.ID, 10)) } // UpdateLocalCopy fetches latest changes of given branch from repoPath to localPath. @@ -705,7 +709,7 @@ func (r *Repository) PatchPath(index int64) (string, error) { return "", err } - return filepath.Join(RepoPath(r.Owner.Name, r.Name), "pulls", com.ToStr(index)+".patch"), nil + return filepath.Join(RepoPath(r.Owner.Name, r.Name), "pulls", strconv.FormatInt(index, 10)+".patch"), nil } // SavePatch saves patch data to corresponding location by given issue ID. @@ -730,7 +734,7 @@ func isRepositoryExist(e Engine, u *User, repoName string) (bool, error) { OwnerID: u.ID, LowerName: strings.ToLower(repoName), }) - return has && com.IsDir(RepoPath(u.Name, repoName)), err + return has && osutil.IsDir(RepoPath(u.Name, repoName)), err } // IsRepositoryExist returns true if the repository with given name under user has already existed. @@ -842,12 +846,14 @@ func MigrateRepository(doer, owner *User, opts MigrateRepoOptions) (*Repository, } // Check if repository is empty. - _, stderr, err := com.ExecCmdDir(repoPath, "git", "log", "-1") + cmd := exec.Command("git", "log", "-1") + cmd.Dir = repoPath + output, err := cmd.CombinedOutput() if err != nil { - if strings.Contains(stderr, "fatal: bad default revision 'HEAD'") { + if strings.Contains(string(output), "fatal: bad default revision 'HEAD'") { repo.IsBare = true } else { - return repo, errors.Newf("check bare: %v - %s", err, stderr) + return repo, errors.Newf("check bare: %v - %s", err, output) } } @@ -1070,7 +1076,7 @@ func initRepository(e Engine, repoPath string, doer *User, repo *Repository, opt return errors.Wrap(err, "set default branch") } - tmpDir := filepath.Join(os.TempDir(), "gogs-"+repo.Name+"-"+com.ToStr(time.Now().Nanosecond())) + tmpDir := filepath.Join(os.TempDir(), "gogs-"+repo.Name+"-"+strconv.Itoa(time.Now().Nanosecond())) // Initialize repository according to user's choice. if opts.AutoInit { @@ -1493,7 +1499,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error // Rename remote wiki repository to new path and delete local copy. wikiPath := WikiPath(owner.Name, repo.Name) - if com.IsExist(wikiPath) { + if osutil.Exist(wikiPath) { RemoveAllWithNotice("Delete repository wiki local copy", repo.LocalWikiPath()) if err = os.Rename(wikiPath, WikiPath(newOwner.Name, repo.Name)); err != nil { return errors.Newf("rename repository wiki: %v", err) @@ -1504,8 +1510,8 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error } func deleteRepoLocalCopy(repoID int64) { - repoWorkingPool.CheckIn(com.ToStr(repoID)) - defer repoWorkingPool.CheckOut(com.ToStr(repoID)) + repoWorkingPool.CheckIn(strconv.FormatInt(repoID, 10)) + defer repoWorkingPool.CheckOut(strconv.FormatInt(repoID, 10)) RemoveAllWithNotice(fmt.Sprintf("Delete repository %d local copy", repoID), repoutil.RepositoryLocalPath(repoID)) } @@ -1535,7 +1541,7 @@ func ChangeRepositoryName(u *User, oldRepoName, newRepoName string) (err error) } wikiPath := repo.WikiPath() - if com.IsExist(wikiPath) { + if osutil.Exist(wikiPath) { if err = os.Rename(wikiPath, WikiPath(u.Name, newRepoName)); err != nil { return errors.Newf("rename repository wiki: %v", err) } @@ -1593,11 +1599,11 @@ func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err e // Create/Remove git-daemon-export-ok for git-daemon daemonExportFile := path.Join(repo.RepoPath(), "git-daemon-export-ok") - if repo.IsPrivate && com.IsExist(daemonExportFile) { + if repo.IsPrivate && osutil.Exist(daemonExportFile) { if err = os.Remove(daemonExportFile); err != nil { log.Error("Failed to remove %s: %v", daemonExportFile, err) } - } else if !repo.IsPrivate && !com.IsExist(daemonExportFile) { + } else if !repo.IsPrivate && !osutil.Exist(daemonExportFile) { if f, err := os.Create(daemonExportFile); err != nil { log.Error("Failed to create %s: %v", daemonExportFile, err) } else { @@ -1929,7 +1935,7 @@ func DeleteOldRepositoryArchives() { basePath := filepath.Join(repo.RepoPath(), "archives") for _, format := range formats { dirPath := filepath.Join(basePath, format) - if !com.IsDir(dirPath) { + if !osutil.IsDir(dirPath) { continue } @@ -1992,7 +1998,7 @@ func gatherMissingRepoRecords() ([]*Repository, error) { if err := x.Where("id > 0").Iterate(new(Repository), func(idx int, bean any) error { repo := bean.(*Repository) - if !com.IsDir(repo.RepoPath()) { + if !osutil.IsDir(repo.RepoPath()) { repos = append(repos, repo) } return nil @@ -2143,7 +2149,7 @@ func repoStatsCheck(checker *repoChecker) { return } for _, result := range results { - id := com.StrTo(result["id"]).MustInt64() + id, _ := strconv.ParseInt(string(result["id"]), 10, 64) log.Trace("Updating %s: %d", checker.desc, id) _, err = x.Exec(checker.correctSQL, id, id) if err != nil { @@ -2204,7 +2210,7 @@ func CheckRepoStats() { log.Error("Select %s: %v", desc, err) } else { for _, result := range results { - id := com.StrTo(result["id"]).MustInt64() + id, _ := strconv.ParseInt(string(result["id"]), 10, 64) log.Trace("Updating %s: %d", desc, id) _, err = x.Exec("UPDATE `repository` SET num_closed_issues=(SELECT COUNT(*) FROM `issue` WHERE repo_id=? AND is_closed=? AND is_pull=?) WHERE id=?", id, true, false, id) if err != nil { @@ -2221,7 +2227,7 @@ func CheckRepoStats() { log.Error("Select repository count 'num_forks': %v", err) } else { for _, result := range results { - id := com.StrTo(result["id"]).MustInt64() + id, _ := strconv.ParseInt(string(result["id"]), 10, 64) log.Trace("Updating repository count 'num_forks': %d", id) repo, err := GetRepositoryByID(id) @@ -2632,8 +2638,8 @@ func (r *Repository) GetForks() ([]*Repository, error) { // func (r *Repository) CreateNewBranch(oldBranch, newBranch string) (err error) { - repoWorkingPool.CheckIn(com.ToStr(r.ID)) - defer repoWorkingPool.CheckOut(com.ToStr(r.ID)) + repoWorkingPool.CheckIn(strconv.FormatInt(r.ID, 10)) + defer repoWorkingPool.CheckOut(strconv.FormatInt(r.ID, 10)) localPath := r.LocalCopyPath() diff --git a/internal/database/repo_branch.go b/internal/database/repo_branch.go index 97d9ec64a..f31585f61 100644 --- a/internal/database/repo_branch.go +++ b/internal/database/repo_branch.go @@ -3,11 +3,11 @@ package database import ( "context" "fmt" + "slices" "strings" "github.com/cockroachdb/errors" "github.com/gogs/git-module" - "github.com/unknwon/com" "gogs.io/gogs/internal/errutil" "gogs.io/gogs/internal/tool" @@ -199,7 +199,7 @@ func UpdateOrgProtectBranch(repo *Repository, protectBranch *ProtectBranch, whit } validTeamIDs = make([]int64, 0, len(teams)) for i := range teams { - if teams[i].HasWriteAccess() && com.IsSliceContainsInt64(teamIDs, teams[i].ID) { + if teams[i].HasWriteAccess() && slices.Contains(teamIDs, teams[i].ID) { validTeamIDs = append(validTeamIDs, teams[i].ID) } } diff --git a/internal/database/repo_editor.go b/internal/database/repo_editor.go index 3d5191ab0..ada47fcf0 100644 --- a/internal/database/repo_editor.go +++ b/internal/database/repo_editor.go @@ -8,18 +8,19 @@ import ( "os/exec" "path" "path/filepath" + "strconv" "strings" "time" "github.com/cockroachdb/errors" gouuid "github.com/satori/go.uuid" - "github.com/unknwon/com" "github.com/gogs/git-module" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/cryptoutil" "gogs.io/gogs/internal/gitutil" + "gogs.io/gogs/internal/ioutil" "gogs.io/gogs/internal/osutil" "gogs.io/gogs/internal/pathutil" "gogs.io/gogs/internal/process" @@ -63,12 +64,12 @@ type ComposeHookEnvsOptions struct { func ComposeHookEnvs(opts ComposeHookEnvsOptions) []string { envs := []string{ "SSH_ORIGINAL_COMMAND=1", - EnvAuthUserID + "=" + com.ToStr(opts.AuthUser.ID), + EnvAuthUserID + "=" + strconv.FormatInt(opts.AuthUser.ID, 10), EnvAuthUserName + "=" + opts.AuthUser.Name, EnvAuthUserEmail + "=" + opts.AuthUser.Email, EnvRepoOwnerName + "=" + opts.OwnerName, EnvRepoOwnerSaltMd5 + "=" + cryptoutil.MD5(opts.OwnerSalt), - EnvRepoID + "=" + com.ToStr(opts.RepoID), + EnvRepoID + "=" + strconv.FormatInt(opts.RepoID, 10), EnvRepoName + "=" + opts.RepoName, EnvRepoCustomHooksPath + "=" + filepath.Join(opts.RepoPath, "custom_hooks"), } @@ -85,7 +86,7 @@ func ComposeHookEnvs(opts ComposeHookEnvsOptions) []string { // discardLocalRepoBranchChanges discards local commits/changes of // given branch to make sure it is even to remote branch. func discardLocalRepoBranchChanges(localPath, branch string) error { - if !com.IsExist(localPath) { + if !osutil.Exist(localPath) { return nil } @@ -146,8 +147,8 @@ func (r *Repository) UpdateRepoFile(doer *User, opts UpdateRepoFileOptions) erro return errors.Errorf("bad tree path %q", opts.NewTreeName) } - repoWorkingPool.CheckIn(com.ToStr(r.ID)) - defer repoWorkingPool.CheckOut(com.ToStr(r.ID)) + repoWorkingPool.CheckIn(strconv.FormatInt(r.ID, 10)) + defer repoWorkingPool.CheckOut(strconv.FormatInt(r.ID, 10)) if err := r.DiscardLocalRepoBranchChanges(opts.OldBranch); err != nil { return errors.Newf("discard local repo branch[%s] changes: %v", opts.OldBranch, err) @@ -249,8 +250,8 @@ func (r *Repository) GetDiffPreview(branch, treePath, content string) (*gitutil. return nil, errors.Errorf("bad tree path %q", treePath) } - repoWorkingPool.CheckIn(com.ToStr(r.ID)) - defer repoWorkingPool.CheckOut(com.ToStr(r.ID)) + repoWorkingPool.CheckIn(strconv.FormatInt(r.ID, 10)) + defer repoWorkingPool.CheckOut(strconv.FormatInt(r.ID, 10)) if err := r.DiscardLocalRepoBranchChanges(branch); err != nil { return nil, errors.Newf("discard local repo branch[%s] changes: %v", branch, err) @@ -322,8 +323,8 @@ func (r *Repository) DeleteRepoFile(doer *User, opts DeleteRepoFileOptions) (err return errors.Errorf("bad tree path %q", opts.TreePath) } - repoWorkingPool.CheckIn(com.ToStr(r.ID)) - defer repoWorkingPool.CheckOut(com.ToStr(r.ID)) + repoWorkingPool.CheckIn(strconv.FormatInt(r.ID, 10)) + defer repoWorkingPool.CheckOut(strconv.FormatInt(r.ID, 10)) if err = r.DiscardLocalRepoBranchChanges(opts.OldBranch); err != nil { return errors.Newf("discard local r branch[%s] changes: %v", opts.OldBranch, err) @@ -562,8 +563,8 @@ func (r *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions) err return errors.Newf("get uploads by UUIDs[%v]: %v", opts.Files, err) } - repoWorkingPool.CheckIn(com.ToStr(r.ID)) - defer repoWorkingPool.CheckOut(com.ToStr(r.ID)) + repoWorkingPool.CheckIn(strconv.FormatInt(r.ID, 10)) + defer repoWorkingPool.CheckOut(strconv.FormatInt(r.ID, 10)) if err = r.DiscardLocalRepoBranchChanges(opts.OldBranch); err != nil { return errors.Newf("discard local r branch[%s] changes: %v", opts.OldBranch, err) @@ -606,7 +607,7 @@ func (r *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions) err return errors.Newf("cannot overwrite symbolic link: %s", upload.Name) } - if err = com.Copy(tmpPath, targetPath); err != nil { + if err = ioutil.CopyFile(tmpPath, targetPath); err != nil { return errors.Newf("copy: %v", err) } } diff --git a/internal/database/ssh_key.go b/internal/database/ssh_key.go index c2d0731d0..81fa514c4 100644 --- a/internal/database/ssh_key.go +++ b/internal/database/ssh_key.go @@ -9,18 +9,19 @@ import ( "os" "path" "path/filepath" + "strconv" "strings" "sync" "time" "github.com/cockroachdb/errors" - "github.com/unknwon/com" "golang.org/x/crypto/ssh" log "unknwon.dev/clog/v2" "xorm.io/xorm" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/errutil" + "gogs.io/gogs/internal/osutil" "gogs.io/gogs/internal/process" ) @@ -210,7 +211,8 @@ func SSHKeygenParsePublicKey(key, keyTestPath, keygenPath string) (string, int, } keyType := strings.Trim(fields[len(fields)-1], "()\r\n") - return strings.ToLower(keyType), com.StrTo(fields[0]).MustInt(), nil + length, _ := strconv.Atoi(fields[0]) + return strings.ToLower(keyType), length, nil } // SSHNativeParsePublicKey extracts the key type and length using the golang SSH library. @@ -540,7 +542,7 @@ func RewriteAuthorizedKeys() error { return err } - if com.IsExist(fpath) { + if osutil.Exist(fpath) { if err = os.Remove(fpath); err != nil { return err } diff --git a/internal/database/two_factor.go b/internal/database/two_factor.go index 90eef9b92..95fc93306 100644 --- a/internal/database/two_factor.go +++ b/internal/database/two_factor.go @@ -7,7 +7,6 @@ import ( "github.com/cockroachdb/errors" "github.com/pquerna/otp/totp" - "github.com/unknwon/com" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/cryptoutil" @@ -29,7 +28,7 @@ func (t *TwoFactor) ValidateTOTP(passcode string) (bool, error) { if err != nil { return false, errors.Newf("DecodeString: %v", err) } - decryptSecret, err := com.AESGCMDecrypt(cryptoutil.MD5Bytes(conf.Security.SecretKey), secret) + decryptSecret, err := cryptoutil.AESGCMDecrypt(cryptoutil.MD5Bytes(conf.Security.SecretKey), secret) if err != nil { return false, errors.Newf("AESGCMDecrypt: %v", err) } diff --git a/internal/database/wiki.go b/internal/database/wiki.go index 3039b4ac8..428585d76 100644 --- a/internal/database/wiki.go +++ b/internal/database/wiki.go @@ -5,15 +5,16 @@ import ( "os" "path" "path/filepath" + "strconv" "strings" "time" "github.com/cockroachdb/errors" - "github.com/unknwon/com" "github.com/gogs/git-module" "gogs.io/gogs/internal/conf" + "gogs.io/gogs/internal/osutil" "gogs.io/gogs/internal/pathutil" "gogs.io/gogs/internal/repoutil" "gogs.io/gogs/internal/sync" @@ -61,7 +62,7 @@ func (r *Repository) WikiPath() string { // HasWiki returns true if repository has wiki. func (r *Repository) HasWiki() bool { - return com.IsDir(r.WikiPath()) + return osutil.IsDir(r.WikiPath()) } // InitWiki initializes a wiki for repository, @@ -80,7 +81,7 @@ func (r *Repository) InitWiki() error { } func (r *Repository) LocalWikiPath() string { - return filepath.Join(conf.Server.AppDataPath, "tmp", "local-wiki", com.ToStr(r.ID)) + return filepath.Join(conf.Server.AppDataPath, "tmp", "local-wiki", strconv.FormatInt(r.ID, 10)) } // UpdateLocalWiki makes sure the local copy of repository wiki is up-to-date. @@ -95,8 +96,8 @@ func discardLocalWikiChanges(localPath string) error { // updateWikiPage adds new page to repository wiki. func (r *Repository) updateWikiPage(doer *User, oldTitle, title, content, message string, isNew bool) error { - wikiWorkingPool.CheckIn(com.ToStr(r.ID)) - defer wikiWorkingPool.CheckOut(com.ToStr(r.ID)) + wikiWorkingPool.CheckIn(strconv.FormatInt(r.ID, 10)) + defer wikiWorkingPool.CheckOut(strconv.FormatInt(r.ID, 10)) if err := r.InitWiki(); err != nil { return errors.Newf("InitWiki: %v", err) @@ -114,7 +115,7 @@ func (r *Repository) updateWikiPage(doer *User, oldTitle, title, content, messag // If not a new file, show perform update not create. if isNew { - if com.IsExist(filename) { + if osutil.Exist(filename) { return ErrWikiAlreadyExist{filename} } } else { @@ -167,8 +168,8 @@ func (r *Repository) EditWikiPage(doer *User, oldTitle, title, content, message } func (r *Repository) DeleteWikiPage(doer *User, title string) (err error) { - wikiWorkingPool.CheckIn(com.ToStr(r.ID)) - defer wikiWorkingPool.CheckOut(com.ToStr(r.ID)) + wikiWorkingPool.CheckIn(strconv.FormatInt(r.ID, 10)) + defer wikiWorkingPool.CheckOut(strconv.FormatInt(r.ID, 10)) localPath := r.LocalWikiPath() if err = discardLocalWikiChanges(localPath); err != nil { diff --git a/internal/form/repo.go b/internal/form/repo.go index 9351ea919..f0fffe3fd 100644 --- a/internal/form/repo.go +++ b/internal/form/repo.go @@ -5,12 +5,12 @@ import ( "strings" "github.com/go-macaron/binding" - "github.com/unknwon/com" "gopkg.in/macaron.v1" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/database" "gogs.io/gogs/internal/netutil" + "gogs.io/gogs/internal/osutil" ) // _______________________________________ _________.______________________ _______________.___. @@ -82,7 +82,7 @@ func (f MigrateRepo) ParseRemoteAddr(user *database.User) (string, error) { remoteAddr = u.String() } else if !user.CanImportLocal() { return "", database.ErrInvalidCloneAddr{IsPermissionDenied: true} - } else if !com.IsDir(remoteAddr) { + } else if !osutil.IsDir(remoteAddr) { return "", database.ErrInvalidCloneAddr{IsInvalidPath: true} } diff --git a/internal/ioutil/ioutil.go b/internal/ioutil/ioutil.go new file mode 100644 index 000000000..3876fc776 --- /dev/null +++ b/internal/ioutil/ioutil.go @@ -0,0 +1,47 @@ +package ioutil + +import ( + "io" + "os" + + "github.com/cockroachdb/errors" +) + +// CopyFile copies the file at src to dst, preserving file mode and +// modification time. +func CopyFile(src, dst string) error { + si, err := os.Stat(src) + if err != nil { + return errors.Wrap(err, "stat source") + } + + in, err := os.Open(src) + if err != nil { + return errors.Wrap(err, "open source") + } + defer in.Close() + + out, err := os.Create(dst) + if err != nil { + return errors.Wrap(err, "create target") + } + defer out.Close() + + if _, err = io.Copy(out, in); err != nil { + return errors.Wrap(err, "copy") + } + + if err = out.Sync(); err != nil { + return errors.Wrap(err, "sync target") + } + + if err = os.Chmod(dst, si.Mode()); err != nil { + return errors.Wrap(err, "chmod target") + } + + if err = os.Chtimes(dst, si.ModTime(), si.ModTime()); err != nil { + return errors.Wrap(err, "chtimes target") + } + + return nil +} diff --git a/internal/markup/markup.go b/internal/markup/markup.go index 11d89af26..8bb892761 100644 --- a/internal/markup/markup.go +++ b/internal/markup/markup.go @@ -4,6 +4,8 @@ import ( "bytes" "fmt" "io" + "slices" + "strconv" "strings" "github.com/unknwon/com" @@ -138,7 +140,7 @@ func RenderCrossReferenceIssueIndexPattern(rawBytes []byte, _ string, _ map[stri // RenderSha1CurrentPattern renders SHA1 strings to corresponding links that assumes in the same repository. func RenderSha1CurrentPattern(rawBytes []byte, urlPrefix string) []byte { return []byte(Sha1CurrentPattern.ReplaceAllStringFunc(string(rawBytes), func(m string) string { - if com.StrTo(m).MustInt() > 0 { + if v, _ := strconv.Atoi(m); v > 0 { return m } @@ -264,7 +266,7 @@ outerLoop: buf.WriteString(token.String()) // Stack number doesn't increase for tags without end tags. - if token.Type == html.StartTagToken && !com.IsSliceContainsStr(noEndTags, token.Data) { + if token.Type == html.StartTagToken && !slices.Contains(noEndTags, token.Data) { stackNum++ } @@ -279,7 +281,7 @@ outerLoop: continue outerLoop } - if !com.IsSliceContainsStr(noEndTags, tagName) { + if !slices.Contains(noEndTags, tagName) { startTags = append(startTags, tagName) } diff --git a/internal/route/admin/auths.go b/internal/route/admin/auths.go index dfdf9a4e4..b0f58c7f8 100644 --- a/internal/route/admin/auths.go +++ b/internal/route/admin/auths.go @@ -3,9 +3,9 @@ package admin import ( "fmt" "net/http" + "strconv" "strings" - "github.com/unknwon/com" log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/auth" @@ -269,7 +269,7 @@ func EditAuthSourcePost(c *context.Context, f form.Authentication) { log.Trace("Authentication changed by admin '%s': %d", c.User.Name, source.ID) c.Flash.Success(c.Tr("admin.auths.update_success")) - c.Redirect(conf.Server.Subpath + "/admin/auths/" + com.ToStr(f.ID)) + c.Redirect(conf.Server.Subpath + "/admin/auths/" + strconv.FormatInt(f.ID, 10)) } func DeleteAuthSource(c *context.Context) { diff --git a/internal/route/admin/notice.go b/internal/route/admin/notice.go index d0cdc8e22..9ddff20c1 100644 --- a/internal/route/admin/notice.go +++ b/internal/route/admin/notice.go @@ -2,8 +2,8 @@ package admin import ( "net/http" + "strconv" - "github.com/unknwon/com" "github.com/unknwon/paginater" log "unknwon.dev/clog/v2" @@ -40,7 +40,7 @@ func DeleteNotices(c *context.Context) { strs := c.QueryStrings("ids[]") ids := make([]int64, 0, len(strs)) for i := range strs { - id := com.StrTo(strs[i]).MustInt64() + id, _ := strconv.ParseInt(strs[i], 10, 64) if id > 0 { ids = append(ids, id) } diff --git a/internal/route/api/v1/convert/convert.go b/internal/route/api/v1/convert/convert.go index f6447f334..a4e5769ce 100644 --- a/internal/route/api/v1/convert/convert.go +++ b/internal/route/api/v1/convert/convert.go @@ -3,8 +3,7 @@ package convert import ( "context" "fmt" - - "github.com/unknwon/com" + "strconv" "github.com/gogs/git-module" api "github.com/gogs/go-gogs-client" @@ -72,7 +71,7 @@ func ToPublicKey(apiLink string, key *database.PublicKey) *api.PublicKey { return &api.PublicKey{ ID: key.ID, Key: key.Content, - URL: apiLink + com.ToStr(key.ID), + URL: apiLink + strconv.FormatInt(key.ID, 10), Title: key.Name, Created: key.Created, } @@ -107,7 +106,7 @@ func ToDeployKey(apiLink string, key *database.DeployKey) *api.DeployKey { return &api.DeployKey{ ID: key.ID, Key: key.Content, - URL: apiLink + com.ToStr(key.ID), + URL: apiLink + strconv.FormatInt(key.ID, 10), Title: key.Name, Created: key.Created, ReadOnly: true, // All deploy keys are read-only. diff --git a/internal/route/api/v1/repo/hook.go b/internal/route/api/v1/repo/hook.go index 21069adbb..fca6e55f9 100644 --- a/internal/route/api/v1/repo/hook.go +++ b/internal/route/api/v1/repo/hook.go @@ -2,10 +2,10 @@ package repo import ( "net/http" + "slices" "github.com/cockroachdb/errors" jsoniter "github.com/json-iterator/go" - "github.com/unknwon/com" api "github.com/gogs/go-gogs-client" @@ -57,14 +57,14 @@ func CreateHook(c *context.APIContext, form api.CreateHookOption) { HookEvent: &database.HookEvent{ ChooseEvents: true, HookEvents: database.HookEvents{ - Create: com.IsSliceContainsStr(form.Events, string(database.HookEventTypeCreate)), - Delete: com.IsSliceContainsStr(form.Events, string(database.HookEventTypeDelete)), - Fork: com.IsSliceContainsStr(form.Events, string(database.HookEventTypeFork)), - Push: com.IsSliceContainsStr(form.Events, string(database.HookEventTypePush)), - Issues: com.IsSliceContainsStr(form.Events, string(database.HookEventTypeIssues)), - IssueComment: com.IsSliceContainsStr(form.Events, string(database.HookEventTypeIssueComment)), - PullRequest: com.IsSliceContainsStr(form.Events, string(database.HookEventTypePullRequest)), - Release: com.IsSliceContainsStr(form.Events, string(database.HookEventTypeRelease)), + Create: slices.Contains(form.Events, string(database.HookEventTypeCreate)), + Delete: slices.Contains(form.Events, string(database.HookEventTypeDelete)), + Fork: slices.Contains(form.Events, string(database.HookEventTypeFork)), + Push: slices.Contains(form.Events, string(database.HookEventTypePush)), + Issues: slices.Contains(form.Events, string(database.HookEventTypeIssues)), + IssueComment: slices.Contains(form.Events, string(database.HookEventTypeIssueComment)), + PullRequest: slices.Contains(form.Events, string(database.HookEventTypePullRequest)), + Release: slices.Contains(form.Events, string(database.HookEventTypeRelease)), }, }, IsActive: form.Active, @@ -144,14 +144,14 @@ func EditHook(c *context.APIContext, form api.EditHookOption) { w.PushOnly = false w.SendEverything = false w.ChooseEvents = true - w.Create = com.IsSliceContainsStr(form.Events, string(database.HookEventTypeCreate)) - w.Delete = com.IsSliceContainsStr(form.Events, string(database.HookEventTypeDelete)) - w.Fork = com.IsSliceContainsStr(form.Events, string(database.HookEventTypeFork)) - w.Push = com.IsSliceContainsStr(form.Events, string(database.HookEventTypePush)) - w.Issues = com.IsSliceContainsStr(form.Events, string(database.HookEventTypeIssues)) - w.IssueComment = com.IsSliceContainsStr(form.Events, string(database.HookEventTypeIssueComment)) - w.PullRequest = com.IsSliceContainsStr(form.Events, string(database.HookEventTypePullRequest)) - w.Release = com.IsSliceContainsStr(form.Events, string(database.HookEventTypeRelease)) + w.Create = slices.Contains(form.Events, string(database.HookEventTypeCreate)) + w.Delete = slices.Contains(form.Events, string(database.HookEventTypeDelete)) + w.Fork = slices.Contains(form.Events, string(database.HookEventTypeFork)) + w.Push = slices.Contains(form.Events, string(database.HookEventTypePush)) + w.Issues = slices.Contains(form.Events, string(database.HookEventTypeIssues)) + w.IssueComment = slices.Contains(form.Events, string(database.HookEventTypeIssueComment)) + w.PullRequest = slices.Contains(form.Events, string(database.HookEventTypePullRequest)) + w.Release = slices.Contains(form.Events, string(database.HookEventTypeRelease)) if err = w.UpdateEvent(); err != nil { c.Errorf(err, "update event") return diff --git a/internal/route/api/v1/repo/label.go b/internal/route/api/v1/repo/label.go index d17cf90c3..f663a8e8a 100644 --- a/internal/route/api/v1/repo/label.go +++ b/internal/route/api/v1/repo/label.go @@ -2,9 +2,9 @@ package repo import ( "net/http" + "strconv" api "github.com/gogs/go-gogs-client" - "github.com/unknwon/com" "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/database" @@ -28,7 +28,7 @@ func GetLabel(c *context.APIContext) { var label *database.Label var err error idStr := c.Params(":id") - if id := com.StrTo(idStr).MustInt64(); id > 0 { + if id, _ := strconv.ParseInt(idStr, 10, 64); id > 0 { label, err = database.GetLabelOfRepoByID(c.Repo.Repository.ID, id) } else { label, err = database.GetLabelOfRepoByName(c.Repo.Repository.ID, idStr) diff --git a/internal/route/install.go b/internal/route/install.go index ddbabe401..d3b3b6510 100644 --- a/internal/route/install.go +++ b/internal/route/install.go @@ -6,11 +6,11 @@ import ( "os" "os/exec" "path/filepath" + "strconv" "strings" "github.com/cockroachdb/errors" "github.com/gogs/git-module" - "github.com/unknwon/com" "gopkg.in/ini.v1" "gopkg.in/macaron.v1" log "unknwon.dev/clog/v2" @@ -330,8 +330,8 @@ func InstallPost(c *context.Context, f form.Install) { cfg.Section("server").Key("DISABLE_SSH").SetValue("true") } else { cfg.Section("server").Key("DISABLE_SSH").SetValue("false") - cfg.Section("server").Key("SSH_PORT").SetValue(com.ToStr(f.SSHPort)) - cfg.Section("server").Key("START_SSH_SERVER").SetValue(com.ToStr(f.UseBuiltinSSHServer)) + cfg.Section("server").Key("SSH_PORT").SetValue(strconv.Itoa(f.SSHPort)) + cfg.Section("server").Key("START_SSH_SERVER").SetValue(strconv.FormatBool(f.UseBuiltinSSHServer)) } if len(strings.TrimSpace(f.SMTPHost)) > 0 { @@ -343,14 +343,14 @@ func InstallPost(c *context.Context, f form.Install) { } else { cfg.Section("email").Key("ENABLED").SetValue("false") } - cfg.Section("server").Key("OFFLINE_MODE").SetValue(com.ToStr(f.OfflineMode)) - cfg.Section("auth").Key("REQUIRE_EMAIL_CONFIRMATION").SetValue(com.ToStr(f.RegisterConfirm)) - cfg.Section("auth").Key("DISABLE_REGISTRATION").SetValue(com.ToStr(f.DisableRegistration)) - cfg.Section("auth").Key("ENABLE_REGISTRATION_CAPTCHA").SetValue(com.ToStr(f.EnableCaptcha)) - cfg.Section("auth").Key("REQUIRE_SIGNIN_VIEW").SetValue(com.ToStr(f.RequireSignInView)) - cfg.Section("user").Key("ENABLE_EMAIL_NOTIFICATION").SetValue(com.ToStr(f.MailNotify)) - cfg.Section("picture").Key("DISABLE_GRAVATAR").SetValue(com.ToStr(f.DisableGravatar)) - cfg.Section("picture").Key("ENABLE_FEDERATED_AVATAR").SetValue(com.ToStr(f.EnableFederatedAvatar)) + cfg.Section("server").Key("OFFLINE_MODE").SetValue(strconv.FormatBool(f.OfflineMode)) + cfg.Section("auth").Key("REQUIRE_EMAIL_CONFIRMATION").SetValue(strconv.FormatBool(f.RegisterConfirm)) + cfg.Section("auth").Key("DISABLE_REGISTRATION").SetValue(strconv.FormatBool(f.DisableRegistration)) + cfg.Section("auth").Key("ENABLE_REGISTRATION_CAPTCHA").SetValue(strconv.FormatBool(f.EnableCaptcha)) + cfg.Section("auth").Key("REQUIRE_SIGNIN_VIEW").SetValue(strconv.FormatBool(f.RequireSignInView)) + cfg.Section("user").Key("ENABLE_EMAIL_NOTIFICATION").SetValue(strconv.FormatBool(f.MailNotify)) + cfg.Section("picture").Key("DISABLE_GRAVATAR").SetValue(strconv.FormatBool(f.DisableGravatar)) + cfg.Section("picture").Key("ENABLE_FEDERATED_AVATAR").SetValue(strconv.FormatBool(f.EnableFederatedAvatar)) cfg.Section("").Key("RUN_MODE").SetValue("prod") diff --git a/internal/route/org/members.go b/internal/route/org/members.go index 7c70285af..3a42f7944 100644 --- a/internal/route/org/members.go +++ b/internal/route/org/members.go @@ -1,7 +1,8 @@ package org import ( - "github.com/unknwon/com" + "strconv" + log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/conf" @@ -29,7 +30,7 @@ func Members(c *context.Context) { } func MembersAction(c *context.Context) { - uid := com.StrTo(c.Query("uid")).MustInt64() + uid, _ := strconv.ParseInt(c.Query("uid"), 10, 64) if uid == 0 { c.Redirect(c.Org.OrgLink + "/members") return diff --git a/internal/route/org/teams.go b/internal/route/org/teams.go index f13e7ba84..e7f306fec 100644 --- a/internal/route/org/teams.go +++ b/internal/route/org/teams.go @@ -3,8 +3,8 @@ package org import ( "net/http" "path" + "strconv" - "github.com/unknwon/com" log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/context" @@ -36,7 +36,7 @@ func Teams(c *context.Context) { } func TeamsAction(c *context.Context) { - uid := com.StrTo(c.Query("uid")).MustInt64() + uid, _ := strconv.ParseInt(c.Query("uid"), 10, 64) if uid == 0 { c.Redirect(c.Org.OrgLink + "/teams") return @@ -127,7 +127,8 @@ func TeamsRepoAction(c *context.Context) { } err = c.Org.Team.AddRepository(repo) case "remove": - err = c.Org.Team.RemoveRepository(com.StrTo(c.Query("repoid")).MustInt64()) + repoID, _ := strconv.ParseInt(c.Query("repoid"), 10, 64) + err = c.Org.Team.RemoveRepository(repoID) } if err != nil { diff --git a/internal/route/repo/issue.go b/internal/route/repo/issue.go index ed1b6c664..fc31ededb 100644 --- a/internal/route/repo/issue.go +++ b/internal/route/repo/issue.go @@ -5,11 +5,11 @@ import ( "net/http" "net/url" "slices" + "strconv" "strings" "time" "github.com/cockroachdb/errors" - "github.com/unknwon/com" "github.com/unknwon/paginater" log "unknwon.dev/clog/v2" @@ -103,7 +103,7 @@ func issues(c *context.Context, isPullList bool) { viewType := c.Query("type") sortType := c.Query("sort") types := []string{"assigned", "created_by", "mentioned"} - if !com.IsSliceContainsStr(types, viewType) { + if !slices.Contains(types, viewType) { viewType = "all" } @@ -221,7 +221,8 @@ func issues(c *context.Context, isPullList bool) { } c.Data["IssueStats"] = issueStats - c.Data["SelectLabels"] = com.StrTo(selectLabels).MustInt64() + selectLabelsInt, _ := strconv.ParseInt(selectLabels, 10, 64) + c.Data["SelectLabels"] = selectLabelsInt c.Data["ViewType"] = viewType c.Data["SortType"] = sortType c.Data["MilestoneID"] = milestoneID diff --git a/internal/route/repo/pull.go b/internal/route/repo/pull.go index 1616e790c..068e336fa 100644 --- a/internal/route/repo/pull.go +++ b/internal/route/repo/pull.go @@ -3,10 +3,10 @@ package repo import ( "net/http" "path" + "strconv" "strings" "time" - "github.com/unknwon/com" log "unknwon.dev/clog/v2" "github.com/gogs/git-module" @@ -427,7 +427,7 @@ func MergePullRequest(c *context.Context) { } log.Trace("Pull request merged: %d", pr.ID) - c.Redirect(c.Repo.RepoLink + "/pulls/" + com.ToStr(pr.Index)) + c.Redirect(c.Repo.RepoLink + "/pulls/" + strconv.FormatInt(pr.Index, 10)) } func ParseCompareInfo(c *context.Context) (*database.User, *database.Repository, *git.Repository, *gitutil.PullRequestMeta, string, string) { @@ -752,5 +752,5 @@ func CompareAndPullRequestPost(c *context.Context, f form.NewIssue) { } log.Trace("Pull request created: %d/%d", repo.ID, pullIssue.ID) - c.Redirect(c.Repo.RepoLink + "/pulls/" + com.ToStr(pullIssue.Index)) + c.Redirect(c.Repo.RepoLink + "/pulls/" + strconv.FormatInt(pullIssue.Index, 10)) } diff --git a/internal/route/repo/repo.go b/internal/route/repo/repo.go index d81971bc4..d023dfba2 100644 --- a/internal/route/repo/repo.go +++ b/internal/route/repo/repo.go @@ -7,7 +7,6 @@ import ( "path/filepath" "strings" - "github.com/unknwon/com" log "unknwon.dev/clog/v2" "github.com/gogs/git-module" @@ -16,6 +15,7 @@ import ( "gogs.io/gogs/internal/context" "gogs.io/gogs/internal/database" "gogs.io/gogs/internal/form" + "gogs.io/gogs/internal/osutil" "gogs.io/gogs/internal/tool" "gogs.io/gogs/internal/urlutil" ) @@ -292,7 +292,7 @@ func Download(c *context.Context) { } refName = strings.TrimSuffix(uri, ext) - if !com.IsDir(archivePath) { + if !osutil.IsDir(archivePath) { if err := os.MkdirAll(archivePath, os.ModePerm); err != nil { c.Error(err, "create archive directory") return @@ -329,7 +329,7 @@ func Download(c *context.Context) { } archivePath = path.Join(archivePath, tool.ShortSHA1(commit.ID.String())+ext) - if !com.IsFile(archivePath) { + if !osutil.IsFile(archivePath) { if err := commit.CreateArchive(archiveFormat, archivePath); err != nil { c.Error(err, "creates archive") return diff --git a/internal/route/repo/setting.go b/internal/route/repo/setting.go index 94abf80bb..de8050b49 100644 --- a/internal/route/repo/setting.go +++ b/internal/route/repo/setting.go @@ -10,7 +10,6 @@ import ( "github.com/cockroachdb/errors" "github.com/gogs/git-module" - "github.com/unknwon/com" log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/conf" @@ -345,7 +344,7 @@ func UpdateAvatarSetting(c *context.Context, f form.Avatar, ctxRepo *database.Re } } else { // No avatar is uploaded and reset setting back. - if !com.IsFile(ctxRepo.CustomAvatarPath()) { + if !osutil.IsFile(ctxRepo.CustomAvatarPath()) { ctxRepo.UseCustomAvatar = false } } diff --git a/internal/route/user/auth.go b/internal/route/user/auth.go index 75232486f..026bce215 100644 --- a/internal/route/user/auth.go +++ b/internal/route/user/auth.go @@ -5,10 +5,10 @@ import ( "encoding/hex" "net/http" "net/url" + "strconv" "github.com/cockroachdb/errors" "github.com/go-macaron/captcha" - "github.com/unknwon/com" log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/auth" @@ -427,7 +427,7 @@ func verifyUserActiveCode(code string) (user *database.User) { if user = parseUserFromCode(code); user != nil { // time limit code prefix := code[:tool.TimeLimitCodeLength] - data := com.ToStr(user.ID) + user.Email + user.LowerName + user.Password + user.Rands + data := strconv.FormatInt(user.ID, 10) + user.Email + user.LowerName + user.Password + user.Rands if tool.VerifyTimeLimitCode(data, minutes, prefix) { return user @@ -443,7 +443,7 @@ func verifyActiveEmailCode(code, email string) *database.EmailAddress { if user := parseUserFromCode(code); user != nil { // time limit code prefix := code[:tool.TimeLimitCodeLength] - data := com.ToStr(user.ID) + email + user.LowerName + user.Password + user.Rands + data := strconv.FormatInt(user.ID, 10) + email + user.LowerName + user.Password + user.Rands if tool.VerifyTimeLimitCode(data, minutes, prefix) { emailAddress, err := database.Handle.Users().GetEmail(gocontext.TODO(), user.ID, email, false) diff --git a/internal/route/user/home.go b/internal/route/user/home.go index 9ab11b050..3940dca12 100644 --- a/internal/route/user/home.go +++ b/internal/route/user/home.go @@ -4,8 +4,8 @@ import ( "bytes" "fmt" "net/http" + "slices" - "github.com/unknwon/com" "github.com/unknwon/paginater" "gogs.io/gogs/internal/conf" @@ -210,7 +210,7 @@ func Issues(c *context.Context) { string(database.FilterModeAssign), string(database.FilterModeCreate), } - if !com.IsSliceContainsStr(types, viewType) { + if !slices.Contains(types, viewType) { viewType = string(database.FilterModeYourRepos) } filterMode = database.FilterMode(viewType) diff --git a/internal/ssh/ssh.go b/internal/ssh/ssh.go index 29665136b..6497681c5 100644 --- a/internal/ssh/ssh.go +++ b/internal/ssh/ssh.go @@ -7,12 +7,12 @@ import ( "os" "os/exec" "path/filepath" + "strconv" "strings" "syscall" "github.com/cockroachdb/errors" "github.com/sourcegraph/run" - "github.com/unknwon/com" "golang.org/x/crypto/ssh" log "unknwon.dev/clog/v2" @@ -107,7 +107,7 @@ func handleServerConn(keyID string, chans <-chan ssh.NewChannel) { } func listen(config *ssh.ServerConfig, host string, port int) { - listener, err := net.Listen("tcp", host+":"+com.ToStr(port)) + listener, err := net.Listen("tcp", host+":"+strconv.Itoa(port)) if err != nil { log.Fatal("Failed to start SSH server: %v", err) } @@ -158,7 +158,7 @@ func Listen(opts conf.SSHOpts, appDataPath string) { } return nil, err } - return &ssh.Permissions{Extensions: map[string]string{"key-id": com.ToStr(pkey.ID)}}, nil + return &ssh.Permissions{Extensions: map[string]string{"key-id": strconv.FormatInt(pkey.ID, 10)}}, nil }, } diff --git a/internal/strutil/strutil.go b/internal/strutil/strutil.go index 96075a367..8cf2c739d 100644 --- a/internal/strutil/strutil.go +++ b/internal/strutil/strutil.go @@ -3,6 +3,7 @@ package strutil import ( "crypto/rand" "math/big" + "strings" "unicode" ) @@ -59,3 +60,13 @@ func Truncate(str string, limit int) string { } return str[:limit] } + +// ContainsFold reports whether s is within the slice, ignoring case. +func ContainsFold(ss []string, s string) bool { + for _, v := range ss { + if strings.EqualFold(v, s) { + return true + } + } + return false +} diff --git a/internal/strutil/strutil_test.go b/internal/strutil/strutil_test.go index 5a6072b15..79bade950 100644 --- a/internal/strutil/strutil_test.go +++ b/internal/strutil/strutil_test.go @@ -131,3 +131,15 @@ func TestTruncate(t *testing.T) { }) } } + +func TestContainsFold(t *testing.T) { + ss := []string{"Alice", "Bob", "Charlie"} + + assert.True(t, ContainsFold(ss, "alice")) + assert.True(t, ContainsFold(ss, "Alice")) + assert.True(t, ContainsFold(ss, "ALICE")) + assert.True(t, ContainsFold(ss, "bob")) + assert.False(t, ContainsFold(ss, "dave")) + assert.False(t, ContainsFold(nil, "alice")) + assert.False(t, ContainsFold([]string{}, "alice")) +} diff --git a/internal/sync/unique_queue.go b/internal/sync/unique_queue.go index 2080b9561..d2f123f18 100644 --- a/internal/sync/unique_queue.go +++ b/internal/sync/unique_queue.go @@ -1,7 +1,7 @@ package sync import ( - "github.com/unknwon/com" + "fmt" ) // UniqueQueue is a queue which guarantees only one instance of same @@ -35,7 +35,7 @@ func (q *UniqueQueue) Queue() <-chan string { // Exist returns true if there is an instance with given identity // exists in the queue. func (q *UniqueQueue) Exist(id any) bool { - return q.table.IsRunning(com.ToStr(id)) + return q.table.IsRunning(fmt.Sprintf("%v", id)) } // AddFunc adds new instance to the queue with a custom runnable function, @@ -45,7 +45,7 @@ func (q *UniqueQueue) AddFunc(id any, fn func()) { return } - idStr := com.ToStr(id) + idStr := fmt.Sprintf("%v", id) q.table.Lock() q.table.pool[idStr] = true if fn != nil { @@ -62,5 +62,5 @@ func (q *UniqueQueue) Add(id any) { // Remove removes instance from the queue. func (q *UniqueQueue) Remove(id any) { - q.table.Stop(com.ToStr(id)) + q.table.Stop(fmt.Sprintf("%v", id)) } diff --git a/internal/tool/tool.go b/internal/tool/tool.go index 3cc6644c0..de6874d28 100644 --- a/internal/tool/tool.go +++ b/internal/tool/tool.go @@ -6,12 +6,12 @@ import ( "encoding/hex" "fmt" "html/template" + "strconv" "strings" "time" "unicode" "unicode/utf8" - "github.com/unknwon/com" "github.com/unknwon/i18n" log "unknwon.dev/clog/v2" @@ -67,7 +67,7 @@ func VerifyTimeLimitCode(data string, minutes int, code string) bool { // split code start := code[:12] lives := code[12:18] - if d, err := com.StrTo(lives).Int(); err == nil { + if d, err := strconv.Atoi(lives); err == nil { minutes = d } @@ -111,7 +111,7 @@ func CreateTimeLimitCode(data string, minutes int, startInf any) string { // create sha1 encode string sh := sha1.New() - _, _ = sh.Write([]byte(data + conf.Security.SecretKey + startStr + endStr + com.ToStr(minutes))) + _, _ = sh.Write([]byte(data + conf.Security.SecretKey + startStr + endStr + strconv.Itoa(minutes))) encoded := hex.EncodeToString(sh.Sum(nil)) code := fmt.Sprintf("%s%06d%s", startStr, minutes, encoded) @@ -148,9 +148,9 @@ func AvatarLink(email string) (url string) { // AppendAvatarSize appends avatar size query parameter to the URL in the correct format. func AppendAvatarSize(url string, size int) string { if strings.Contains(url, "?") { - return url + "&s=" + com.ToStr(size) + return url + "&s=" + strconv.Itoa(size) } - return url + "?s=" + com.ToStr(size) + return url + "?s=" + strconv.Itoa(size) } // Seconds-based time units @@ -348,10 +348,11 @@ func Subtract(left, right any) any { } // StringsToInt64s converts a slice of string to a slice of int64. +// Invalid strings are converted to 0 (parse errors are silently ignored). func StringsToInt64s(strs []string) []int64 { ints := make([]int64, len(strs)) for i := range strs { - ints[i] = com.StrTo(strs[i]).MustInt64() + ints[i], _ = strconv.ParseInt(strs[i], 10, 64) } return ints } @@ -360,7 +361,7 @@ func StringsToInt64s(strs []string) []int64 { func Int64sToStrings(ints []int64) []string { strs := make([]string, len(ints)) for i := range ints { - strs[i] = com.ToStr(ints[i]) + strs[i] = strconv.FormatInt(ints[i], 10) } return strs }