mirror of
https://github.com/go-gitea/gitea.git
synced 2026-05-06 19:18:35 +02:00
Merge branch 'main' into lunny/refactor_review_request
This commit is contained in:
commit
a7016ce8d5
1005
.eslintrc.cjs
1005
.eslintrc.cjs
File diff suppressed because it is too large
Load Diff
6
Makefile
6
Makefile
@ -162,7 +162,7 @@ TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(DIST)
|
||||
GO_DIRS := build cmd models modules routers services tests
|
||||
WEB_DIRS := web_src/js web_src/css
|
||||
|
||||
ESLINT_FILES := web_src/js tools *.ts *.cjs tests/e2e
|
||||
ESLINT_FILES := web_src/js tools *.ts tests/e2e
|
||||
STYLELINT_FILES := web_src/css web_src/js/components/*.vue
|
||||
SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) templates options/locale/locale_en-US.ini .github $(filter-out CHANGELOG.md, $(wildcard *.go *.md *.yml *.yaml *.toml)) $(filter-out tools/misspellings.csv, $(wildcard tools/*))
|
||||
EDITORCONFIG_FILES := templates .github/workflows options/locale/locale_en-US.ini
|
||||
@ -346,12 +346,12 @@ lint-backend-fix: lint-go-fix lint-go-gitea-vet lint-editorconfig ## lint backen
|
||||
|
||||
.PHONY: lint-js
|
||||
lint-js: node_modules ## lint js files
|
||||
$(NODE_VARS) pnpm exec eslint --color --max-warnings=0 --ext js,ts,vue $(ESLINT_FILES)
|
||||
$(NODE_VARS) pnpm exec eslint --color --max-warnings=0 --flag unstable_native_nodejs_ts_config $(ESLINT_FILES)
|
||||
$(NODE_VARS) pnpm exec vue-tsc
|
||||
|
||||
.PHONY: lint-js-fix
|
||||
lint-js-fix: node_modules ## lint js files and fix issues
|
||||
$(NODE_VARS) pnpm exec eslint --color --max-warnings=0 --ext js,ts,vue $(ESLINT_FILES) --fix
|
||||
$(NODE_VARS) pnpm exec eslint --color --max-warnings=0 --flag unstable_native_nodejs_ts_config $(ESLINT_FILES) --fix
|
||||
$(NODE_VARS) pnpm exec vue-tsc
|
||||
|
||||
.PHONY: lint-css
|
||||
|
||||
5
assets/go-licenses.json
generated
5
assets/go-licenses.json
generated
@ -579,11 +579,6 @@
|
||||
"path": "github.com/go-webauthn/x/revoke/LICENSE",
|
||||
"licenseText": "Copyright (c) 2014 CloudFlare Inc.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\nRedistributions of source code must retain the above copyright notice,\nthis list of conditions and the following disclaimer.\n\nRedistributions in binary form must reproduce the above copyright notice,\nthis list of conditions and the following disclaimer in the documentation\nand/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nHOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
|
||||
},
|
||||
{
|
||||
"name": "github.com/gobwas/glob",
|
||||
"path": "github.com/gobwas/glob/LICENSE",
|
||||
"licenseText": "The MIT License (MIT)\n\nCopyright (c) 2016 Sergey Kamardin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
|
||||
},
|
||||
{
|
||||
"name": "github.com/goccy/go-json",
|
||||
"path": "github.com/goccy/go-json/LICENSE",
|
||||
|
||||
@ -265,6 +265,7 @@ func runDump(ctx context.Context, cmd *cli.Command) error {
|
||||
excludes = append(excludes, setting.LFS.Storage.Path)
|
||||
excludes = append(excludes, setting.Attachment.Storage.Path)
|
||||
excludes = append(excludes, setting.Packages.Storage.Path)
|
||||
excludes = append(excludes, setting.RepoArchive.Storage.Path)
|
||||
excludes = append(excludes, setting.Log.RootPath)
|
||||
if err := dumper.AddRecursiveExclude("data", setting.AppDataPath, excludes); err != nil {
|
||||
fatal("Failed to include data directory: %v", err)
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/assetfs"
|
||||
"code.gitea.io/gitea/modules/glob"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/options"
|
||||
"code.gitea.io/gitea/modules/public"
|
||||
@ -19,7 +20,6 @@ import (
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@ import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
repo_module "code.gitea.io/gitea/modules/repository"
|
||||
@ -312,7 +313,7 @@ func runHookPostReceive(ctx context.Context, c *cli.Command) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
|
||||
// First of all run update-server-info no matter what
|
||||
if _, _, err := git.NewCommand("update-server-info").RunStdString(ctx, nil); err != nil {
|
||||
if _, _, err := gitcmd.NewCommand("update-server-info").RunStdString(ctx, nil); err != nil {
|
||||
return fmt.Errorf("failed to call 'git update-server-info': %w", err)
|
||||
}
|
||||
|
||||
|
||||
31
cmd/serv.go
31
cmd/serv.go
@ -21,6 +21,7 @@ import (
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
"code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/lfstransfer"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
@ -312,30 +313,30 @@ func runServ(ctx context.Context, c *cli.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var gitcmd *exec.Cmd
|
||||
gitBinPath := filepath.Dir(git.GitExecutable) // e.g. /usr/bin
|
||||
gitBinVerb := filepath.Join(gitBinPath, verb) // e.g. /usr/bin/git-upload-pack
|
||||
var command *exec.Cmd
|
||||
gitBinPath := filepath.Dir(gitcmd.GitExecutable) // e.g. /usr/bin
|
||||
gitBinVerb := filepath.Join(gitBinPath, verb) // e.g. /usr/bin/git-upload-pack
|
||||
if _, err := os.Stat(gitBinVerb); err != nil {
|
||||
// if the command "git-upload-pack" doesn't exist, try to split "git-upload-pack" to use the sub-command with git
|
||||
// ps: Windows only has "git.exe" in the bin path, so Windows always uses this way
|
||||
verbFields := strings.SplitN(verb, "-", 2)
|
||||
if len(verbFields) == 2 {
|
||||
// use git binary with the sub-command part: "C:\...\bin\git.exe", "upload-pack", ...
|
||||
gitcmd = exec.CommandContext(ctx, git.GitExecutable, verbFields[1], repoPath)
|
||||
command = exec.CommandContext(ctx, gitcmd.GitExecutable, verbFields[1], repoPath)
|
||||
}
|
||||
}
|
||||
if gitcmd == nil {
|
||||
if command == nil {
|
||||
// by default, use the verb (it has been checked above by allowedCommands)
|
||||
gitcmd = exec.CommandContext(ctx, gitBinVerb, repoPath)
|
||||
command = exec.CommandContext(ctx, gitBinVerb, repoPath)
|
||||
}
|
||||
|
||||
process.SetSysProcAttribute(gitcmd)
|
||||
gitcmd.Dir = setting.RepoRootPath
|
||||
gitcmd.Stdout = os.Stdout
|
||||
gitcmd.Stdin = os.Stdin
|
||||
gitcmd.Stderr = os.Stderr
|
||||
gitcmd.Env = append(gitcmd.Env, os.Environ()...)
|
||||
gitcmd.Env = append(gitcmd.Env,
|
||||
process.SetSysProcAttribute(command)
|
||||
command.Dir = setting.RepoRootPath
|
||||
command.Stdout = os.Stdout
|
||||
command.Stdin = os.Stdin
|
||||
command.Stderr = os.Stderr
|
||||
command.Env = append(command.Env, os.Environ()...)
|
||||
command.Env = append(command.Env,
|
||||
repo_module.EnvRepoIsWiki+"="+strconv.FormatBool(results.IsWiki),
|
||||
repo_module.EnvRepoName+"="+results.RepoName,
|
||||
repo_module.EnvRepoUsername+"="+results.OwnerName,
|
||||
@ -350,9 +351,9 @@ func runServ(ctx context.Context, c *cli.Command) error {
|
||||
)
|
||||
// to avoid breaking, here only use the minimal environment variables for the "gitea serv" command.
|
||||
// it could be re-considered whether to use the same git.CommonGitCmdEnvs() as "git" command later.
|
||||
gitcmd.Env = append(gitcmd.Env, git.CommonCmdServEnvs()...)
|
||||
command.Env = append(command.Env, gitcmd.CommonCmdServEnvs()...)
|
||||
|
||||
if err = gitcmd.Run(); err != nil {
|
||||
if err = command.Run(); err != nil {
|
||||
return fail(ctx, "Failed to execute git command", "Failed to execute git command: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ The default version will read from `docs/config.yml`. You can override this
|
||||
using the option `--version`.
|
||||
|
||||
The upstream branches will be fetched, using the remote `origin`. This can
|
||||
be overrided using `--upstream`, and fetching can be avoided using
|
||||
be overridden using `--upstream`, and fetching can be avoided using
|
||||
`--no-fetch`.
|
||||
|
||||
By default the branch created will be called `backport-$PR-$VERSION`. You
|
||||
|
||||
@ -150,7 +150,7 @@
|
||||
|
||||
<p>In general, Your Gitea Instance retains User Personal Information for as long as your account is active, or as needed to provide you service.</p>
|
||||
|
||||
<p>If you would like to cancel your account or delete your User Personal Information, you may do so in your user profile. We retain and use your information as necessary to comply with our legal obligations, resolve disputes, and enforce our agreements, but barring legal requirements, we will delete your full profile (within reason) within 90 days of your request. Feel free to contact our support to request erasure of the data we process on the bassis of consent within 30 days.</p>
|
||||
<p>If you would like to cancel your account or delete your User Personal Information, you may do so in your user profile. We retain and use your information as necessary to comply with our legal obligations, resolve disputes, and enforce our agreements, but barring legal requirements, we will delete your full profile (within reason) within 90 days of your request. Feel free to contact our support to request erasure of the data we process on the basis of consent within 30 days.</p>
|
||||
|
||||
<p>After an account has been deleted, certain data, such as contributions to other Users' repositories and comments in others' issues, will remain. However, we will delete or de-identify your User Personal Information, including your username and email address, from the author field of issues, pull requests, and comments by associating them with a ghost user.</p>
|
||||
|
||||
|
||||
1029
eslint.config.ts
Normal file
1029
eslint.config.ts
Normal file
File diff suppressed because it is too large
Load Diff
1
go.mod
1
go.mod
@ -61,7 +61,6 @@ require (
|
||||
github.com/go-redsync/redsync/v4 v4.13.0
|
||||
github.com/go-sql-driver/mysql v1.9.3
|
||||
github.com/go-webauthn/webauthn v0.13.4
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0
|
||||
|
||||
2
go.sum
2
go.sum
@ -364,8 +364,6 @@ github.com/go-webauthn/webauthn v0.13.4 h1:q68qusWPcqHbg9STSxBLBHnsKaLxNO0RnVKaA
|
||||
github.com/go-webauthn/webauthn v0.13.4/go.mod h1:MglN6OH9ECxvhDqoq1wMoF6P6JRYDiQpC9nc5OomQmI=
|
||||
github.com/go-webauthn/x v0.1.24 h1:6LaWf2zzWqbyKT8IyQkhje1/1KCGhlEkMz4V1tDnt/A=
|
||||
github.com/go-webauthn/x v0.1.24/go.mod h1:2o5XKJ+X1AKqYKGgHdKflGnoQFQZ6flJ2IFCBKSbSOw=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
||||
|
||||
@ -25,7 +25,7 @@ type CommitVerification struct {
|
||||
SigningUser *user_model.User // if Verified, then SigningUser is non-nil
|
||||
CommittingUser *user_model.User // if Verified, then CommittingUser is non-nil
|
||||
SigningEmail string
|
||||
SigningKey *GPGKey
|
||||
SigningKey *GPGKey // FIXME: need to refactor it to a new name like "SigningGPGKey", it is also used in some templates
|
||||
SigningSSHKey *PublicKey
|
||||
TrustStatus string
|
||||
}
|
||||
|
||||
37
models/asymkey/key_display.go
Normal file
37
models/asymkey/key_display.go
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
func GetDisplaySigningKey(key *git.SigningKey) string {
|
||||
if key == nil || key.Format == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch key.Format {
|
||||
case git.SigningKeyFormatOpenPGP:
|
||||
return key.KeyID
|
||||
case git.SigningKeyFormatSSH:
|
||||
content, err := os.ReadFile(key.KeyID)
|
||||
if err != nil {
|
||||
log.Error("Unable to read SSH key %s: %v", key.KeyID, err)
|
||||
return "(Unable to read SSH key)"
|
||||
}
|
||||
display, err := CalcFingerprint(string(content))
|
||||
if err != nil {
|
||||
log.Error("Unable to calculate fingerprint for SSH key %s: %v", key.KeyID, err)
|
||||
return "(Unable to calculate fingerprint for SSH key)"
|
||||
}
|
||||
return display
|
||||
}
|
||||
setting.PanicInDevOrTesting("Unknown signing key format: %s", key.Format)
|
||||
return "(Unknown key format)"
|
||||
}
|
||||
@ -67,7 +67,7 @@ func (l *XORMLogBridge) Warn(v ...any) {
|
||||
l.Log(stackLevel, log.WARN, "%s", fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Warnf show warnning log
|
||||
// Warnf show warning log
|
||||
func (l *XORMLogBridge) Warnf(format string, v ...any) {
|
||||
l.Log(stackLevel, log.WARN, format, v...)
|
||||
}
|
||||
|
||||
@ -17,12 +17,11 @@ import (
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/glob"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
"github.com/gobwas/glob/syntax"
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
@ -77,7 +76,7 @@ func init() {
|
||||
// IsRuleNameSpecial return true if it contains special character
|
||||
func IsRuleNameSpecial(ruleName string) bool {
|
||||
for i := 0; i < len(ruleName); i++ {
|
||||
if syntax.Special(ruleName[i]) {
|
||||
if glob.IsSpecialByte(ruleName[i]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,9 +8,8 @@ import (
|
||||
"sort"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/glob"
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
)
|
||||
|
||||
type ProtectedBranchRules []*ProtectedBranch
|
||||
|
||||
@ -11,9 +11,8 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
"code.gitea.io/gitea/modules/glob"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
)
|
||||
|
||||
// ProtectedTag struct
|
||||
|
||||
@ -408,7 +408,7 @@ func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
|
||||
|
||||
official, err := isOfficialReviewer(sess, review.IssueID, reviewer)
|
||||
if err != nil {
|
||||
// Branch might not be proteced or other error, ignore it.
|
||||
// Branch might not be protected or other error, ignore it.
|
||||
continue
|
||||
}
|
||||
review.Official = official
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
@ -83,17 +84,17 @@ func FixMergeBase(ctx context.Context, x *xorm.Engine) error {
|
||||
|
||||
if !pr.HasMerged {
|
||||
var err error
|
||||
pr.MergeBase, _, err = git.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).RunStdString(ctx, &git.RunOpts{Dir: repoPath})
|
||||
pr.MergeBase, _, err = gitcmd.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
var err2 error
|
||||
pr.MergeBase, _, err2 = git.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix+pr.BaseBranch).RunStdString(ctx, &git.RunOpts{Dir: repoPath})
|
||||
pr.MergeBase, _, err2 = gitcmd.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix+pr.BaseBranch).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
if err2 != nil {
|
||||
log.Error("Unable to get merge base for PR ID %d, Index %d in %s/%s. Error: %v & %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err, err2)
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &git.RunOpts{Dir: repoPath})
|
||||
parentsString, _, err := gitcmd.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
|
||||
continue
|
||||
@ -105,9 +106,9 @@ func FixMergeBase(ctx context.Context, x *xorm.Engine) error {
|
||||
|
||||
refs := append([]string{}, parents[1:]...)
|
||||
refs = append(refs, gitRefName)
|
||||
cmd := git.NewCommand("merge-base").AddDashesAndList(refs...)
|
||||
cmd := gitcmd.NewCommand("merge-base").AddDashesAndList(refs...)
|
||||
|
||||
pr.MergeBase, _, err = cmd.RunStdString(ctx, &git.RunOpts{Dir: repoPath})
|
||||
pr.MergeBase, _, err = cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
|
||||
continue
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
@ -80,7 +80,7 @@ func RefixMergeBase(ctx context.Context, x *xorm.Engine) error {
|
||||
|
||||
gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index)
|
||||
|
||||
parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &git.RunOpts{Dir: repoPath})
|
||||
parentsString, _, err := gitcmd.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
|
||||
continue
|
||||
@ -93,9 +93,9 @@ func RefixMergeBase(ctx context.Context, x *xorm.Engine) error {
|
||||
// we should recalculate
|
||||
refs := append([]string{}, parents[1:]...)
|
||||
refs = append(refs, gitRefName)
|
||||
cmd := git.NewCommand("merge-base").AddDashesAndList(refs...)
|
||||
cmd := gitcmd.NewCommand("merge-base").AddDashesAndList(refs...)
|
||||
|
||||
pr.MergeBase, _, err = cmd.RunStdString(ctx, &git.RunOpts{Dir: repoPath})
|
||||
pr.MergeBase, _, err = cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
|
||||
continue
|
||||
|
||||
@ -348,10 +348,8 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
|
||||
|
||||
for _, u := range repo.Units {
|
||||
for _, team := range teams {
|
||||
unitAccessMode := minAccessMode
|
||||
if teamMode, exist := team.UnitAccessModeEx(ctx, u.Type); exist {
|
||||
unitAccessMode = max(perm.unitsMode[u.Type], unitAccessMode, teamMode)
|
||||
}
|
||||
teamMode, _ := team.UnitAccessModeEx(ctx, u.Type)
|
||||
unitAccessMode := max(perm.unitsMode[u.Type], minAccessMode, teamMode)
|
||||
perm.unitsMode[u.Type] = unitAccessMode
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,4 +197,37 @@ func TestGetUserRepoPermission(t *testing.T) {
|
||||
assert.Equal(t, perm_model.AccessModeWrite, perm.unitsMode[unit.TypeCode])
|
||||
assert.Equal(t, perm_model.AccessModeRead, perm.unitsMode[unit.TypeIssues])
|
||||
})
|
||||
|
||||
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) // org private repo, same org as repo 32
|
||||
require.NoError(t, repo3.LoadOwner(ctx))
|
||||
require.True(t, repo3.Owner.IsOrganization())
|
||||
require.NoError(t, db.TruncateBeans(ctx, &organization.TeamUnit{}, &Access{})) // The user has access set of that repo, remove it, it is useless for our test
|
||||
require.NoError(t, db.Insert(ctx, &organization.TeamRepo{OrgID: org.ID, TeamID: team.ID, RepoID: repo3.ID}))
|
||||
t.Run("DoerWithNoopTeamOnPrivateRepo", func(t *testing.T) {
|
||||
perm, err := GetUserRepoPermission(ctx, repo3, user)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, perm_model.AccessModeNone, perm.AccessMode)
|
||||
assert.Equal(t, perm_model.AccessModeNone, perm.unitsMode[unit.TypeCode])
|
||||
assert.Equal(t, perm_model.AccessModeNone, perm.unitsMode[unit.TypeIssues])
|
||||
})
|
||||
|
||||
require.NoError(t, db.Insert(ctx, &organization.TeamUnit{OrgID: org.ID, TeamID: team.ID, Type: unit.TypeCode, AccessMode: perm_model.AccessModeNone}))
|
||||
require.NoError(t, db.Insert(ctx, &organization.TeamUnit{OrgID: org.ID, TeamID: team.ID, Type: unit.TypeIssues, AccessMode: perm_model.AccessModeRead}))
|
||||
t.Run("DoerWithReadIssueTeamOnPrivateRepo", func(t *testing.T) {
|
||||
perm, err := GetUserRepoPermission(ctx, repo3, user)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, perm_model.AccessModeNone, perm.AccessMode)
|
||||
assert.Equal(t, perm_model.AccessModeNone, perm.unitsMode[unit.TypeCode])
|
||||
assert.Equal(t, perm_model.AccessModeRead, perm.unitsMode[unit.TypeIssues])
|
||||
})
|
||||
|
||||
require.NoError(t, db.Insert(ctx, repo_model.Collaboration{RepoID: repo3.ID, UserID: user.ID, Mode: perm_model.AccessModeWrite}))
|
||||
require.NoError(t, db.Insert(ctx, Access{RepoID: repo3.ID, UserID: user.ID, Mode: perm_model.AccessModeWrite}))
|
||||
t.Run("DoerWithReadIssueTeamAndWriteCollaboratorOnPrivateRepo", func(t *testing.T) {
|
||||
perm, err := GetUserRepoPermission(ctx, repo3, user)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, perm_model.AccessModeWrite, perm.AccessMode)
|
||||
assert.Equal(t, perm_model.AccessModeWrite, perm.unitsMode[unit.TypeCode])
|
||||
assert.Equal(t, perm_model.AccessModeWrite, perm.unitsMode[unit.TypeIssues])
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ const (
|
||||
SettingsKeyHiddenCommentTypes = "issue.hidden_comment_types"
|
||||
// SettingsKeyDiffWhitespaceBehavior is the setting key for whitespace behavior of diff
|
||||
SettingsKeyDiffWhitespaceBehavior = "diff.whitespace_behaviour"
|
||||
// SettingsKeyShowOutdatedComments is the setting key wether or not to show outdated comments in PRs
|
||||
// SettingsKeyShowOutdatedComments is the setting key whether or not to show outdated comments in PRs
|
||||
SettingsKeyShowOutdatedComments = "comment_code.show_outdated"
|
||||
|
||||
// UserActivityPubPrivPem is user's private key
|
||||
|
||||
@ -10,11 +10,11 @@ import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/glob"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
webhook_module "code.gitea.io/gitea/modules/webhook"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
"github.com/nektos/act/pkg/jobparser"
|
||||
"github.com/nektos/act/pkg/model"
|
||||
"github.com/nektos/act/pkg/workflowpattern"
|
||||
|
||||
@ -70,7 +70,7 @@ func (i *Identicon) render(c, b1, b2, b1Angle, b2Angle, foreColor int) image.Ima
|
||||
/*
|
||||
# Algorithm
|
||||
|
||||
Origin: An image is splitted into 9 areas
|
||||
Origin: An image is split into 9 areas
|
||||
|
||||
```
|
||||
-------------
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
@ -23,7 +24,7 @@ type BatchChecker struct {
|
||||
stdOut *nulSeparatedAttributeWriter
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
cmd *git.Command
|
||||
cmd *gitcmd.Command
|
||||
}
|
||||
|
||||
// NewBatchChecker creates a check attribute reader for the current repository and provided commit ID
|
||||
@ -76,7 +77,7 @@ func NewBatchChecker(repo *git.Repository, treeish string, attributes []string)
|
||||
_ = lw.Close()
|
||||
}()
|
||||
stdErr := new(bytes.Buffer)
|
||||
err := cmd.Run(ctx, &git.RunOpts{
|
||||
err := cmd.Run(ctx, &gitcmd.RunOpts{
|
||||
Env: envs,
|
||||
Dir: repo.Path,
|
||||
Stdin: stdinReader,
|
||||
|
||||
@ -11,12 +11,13 @@ import (
|
||||
"os"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
func checkAttrCommand(gitRepo *git.Repository, treeish string, filenames, attributes []string) (*git.Command, []string, func(), error) {
|
||||
func checkAttrCommand(gitRepo *git.Repository, treeish string, filenames, attributes []string) (*gitcmd.Command, []string, func(), error) {
|
||||
cancel := func() {}
|
||||
envs := []string{"GIT_FLUSH=1"}
|
||||
cmd := git.NewCommand("check-attr", "-z")
|
||||
cmd := gitcmd.NewCommand("check-attr", "-z")
|
||||
if len(attributes) == 0 {
|
||||
cmd.AddArguments("--all")
|
||||
}
|
||||
@ -70,7 +71,7 @@ func CheckAttributes(ctx context.Context, gitRepo *git.Repository, treeish strin
|
||||
stdOut := new(bytes.Buffer)
|
||||
stdErr := new(bytes.Buffer)
|
||||
|
||||
if err := cmd.Run(ctx, &git.RunOpts{
|
||||
if err := cmd.Run(ctx, &gitcmd.RunOpts{
|
||||
Env: append(os.Environ(), envs...),
|
||||
Dir: gitRepo.Path,
|
||||
Stdout: stdOut,
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
"github.com/djherbis/buffer"
|
||||
@ -29,13 +30,13 @@ type WriteCloserError interface {
|
||||
// This is needed otherwise the git cat-file will hang for invalid repositories.
|
||||
func ensureValidGitRepository(ctx context.Context, repoPath string) error {
|
||||
stderr := strings.Builder{}
|
||||
err := NewCommand("rev-parse").
|
||||
Run(ctx, &RunOpts{
|
||||
err := gitcmd.NewCommand("rev-parse").
|
||||
Run(ctx, &gitcmd.RunOpts{
|
||||
Dir: repoPath,
|
||||
Stderr: &stderr,
|
||||
})
|
||||
if err != nil {
|
||||
return ConcatenateError(err, (&stderr).String())
|
||||
return gitcmd.ConcatenateError(err, (&stderr).String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -61,8 +62,8 @@ func catFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError,
|
||||
|
||||
go func() {
|
||||
stderr := strings.Builder{}
|
||||
err := NewCommand("cat-file", "--batch-check").
|
||||
Run(ctx, &RunOpts{
|
||||
err := gitcmd.NewCommand("cat-file", "--batch-check").
|
||||
Run(ctx, &gitcmd.RunOpts{
|
||||
Dir: repoPath,
|
||||
Stdin: batchStdinReader,
|
||||
Stdout: batchStdoutWriter,
|
||||
@ -71,8 +72,8 @@ func catFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError,
|
||||
UseContextTimeout: true,
|
||||
})
|
||||
if err != nil {
|
||||
_ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
|
||||
_ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String()))
|
||||
_ = batchStdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String()))
|
||||
_ = batchStdinReader.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String()))
|
||||
} else {
|
||||
_ = batchStdoutWriter.Close()
|
||||
_ = batchStdinReader.Close()
|
||||
@ -109,8 +110,8 @@ func catFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufi
|
||||
|
||||
go func() {
|
||||
stderr := strings.Builder{}
|
||||
err := NewCommand("cat-file", "--batch").
|
||||
Run(ctx, &RunOpts{
|
||||
err := gitcmd.NewCommand("cat-file", "--batch").
|
||||
Run(ctx, &gitcmd.RunOpts{
|
||||
Dir: repoPath,
|
||||
Stdin: batchStdinReader,
|
||||
Stdout: batchStdoutWriter,
|
||||
@ -119,8 +120,8 @@ func catFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufi
|
||||
UseContextTimeout: true,
|
||||
})
|
||||
if err != nil {
|
||||
_ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
|
||||
_ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String()))
|
||||
_ = batchStdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String()))
|
||||
_ = batchStdinReader.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String()))
|
||||
} else {
|
||||
_ = batchStdoutWriter.Close()
|
||||
_ = batchStdinReader.Close()
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
@ -141,7 +142,7 @@ func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath
|
||||
}
|
||||
}()
|
||||
|
||||
cmd := NewCommand("blame", "--porcelain")
|
||||
cmd := gitcmd.NewCommand("blame", "--porcelain")
|
||||
|
||||
if DefaultFeatures().CheckVersionAtLeast("2.23") && !bypassBlameIgnore {
|
||||
ignoreRevsFileName, ignoreRevsFileCleanup, err = tryCreateBlameIgnoreRevsFile(commit)
|
||||
@ -165,7 +166,7 @@ func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath
|
||||
go func() {
|
||||
stderr := bytes.Buffer{}
|
||||
// TODO: it doesn't work for directories (the directories shouldn't be "blamed"), and the "err" should be returned by "Read" but not by "Close"
|
||||
err := cmd.Run(ctx, &RunOpts{
|
||||
err := cmd.Run(ctx, &gitcmd.RunOpts{
|
||||
UseContextTimeout: true,
|
||||
Dir: repoPath,
|
||||
Stdout: stdout,
|
||||
|
||||
@ -14,6 +14,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
@ -87,12 +88,12 @@ func (c *Commit) GetCommitByPath(relpath string) (*Commit, error) {
|
||||
|
||||
// AddChanges marks local changes to be ready for commit.
|
||||
func AddChanges(ctx context.Context, repoPath string, all bool, files ...string) error {
|
||||
cmd := NewCommand().AddArguments("add")
|
||||
cmd := gitcmd.NewCommand().AddArguments("add")
|
||||
if all {
|
||||
cmd.AddArguments("--all")
|
||||
}
|
||||
cmd.AddDashesAndList(files...)
|
||||
_, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
_, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -106,7 +107,7 @@ type CommitChangesOptions struct {
|
||||
// CommitChanges commits local changes with given committer, author and message.
|
||||
// If author is nil, it will be the same as committer.
|
||||
func CommitChanges(ctx context.Context, repoPath string, opts CommitChangesOptions) error {
|
||||
cmd := NewCommand()
|
||||
cmd := gitcmd.NewCommand()
|
||||
if opts.Committer != nil {
|
||||
cmd.AddOptionValues("-c", "user.name="+opts.Committer.Name)
|
||||
cmd.AddOptionValues("-c", "user.email="+opts.Committer.Email)
|
||||
@ -121,7 +122,7 @@ func CommitChanges(ctx context.Context, repoPath string, opts CommitChangesOptio
|
||||
}
|
||||
cmd.AddOptionFormat("--message=%s", opts.Message)
|
||||
|
||||
_, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
_, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
// No stderr but exit status 1 means nothing to commit.
|
||||
if err != nil && err.Error() == "exit status 1" {
|
||||
return nil
|
||||
@ -131,7 +132,7 @@ func CommitChanges(ctx context.Context, repoPath string, opts CommitChangesOptio
|
||||
|
||||
// AllCommitsCount returns count of all commits in repository
|
||||
func AllCommitsCount(ctx context.Context, repoPath string, hidePRRefs bool, files ...string) (int64, error) {
|
||||
cmd := NewCommand("rev-list")
|
||||
cmd := gitcmd.NewCommand("rev-list")
|
||||
if hidePRRefs {
|
||||
cmd.AddArguments("--exclude=" + PullPrefix + "*")
|
||||
}
|
||||
@ -140,7 +141,7 @@ func AllCommitsCount(ctx context.Context, repoPath string, hidePRRefs bool, file
|
||||
cmd.AddDashesAndList(files...)
|
||||
}
|
||||
|
||||
stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -160,7 +161,7 @@ type CommitsCountOptions struct {
|
||||
|
||||
// CommitsCount returns number of total commits of until given revision.
|
||||
func CommitsCount(ctx context.Context, opts CommitsCountOptions) (int64, error) {
|
||||
cmd := NewCommand("rev-list", "--count")
|
||||
cmd := gitcmd.NewCommand("rev-list", "--count")
|
||||
|
||||
cmd.AddDynamicArguments(opts.Revision...)
|
||||
|
||||
@ -172,7 +173,7 @@ func CommitsCount(ctx context.Context, opts CommitsCountOptions) (int64, error)
|
||||
cmd.AddDashesAndList(opts.RelPath...)
|
||||
}
|
||||
|
||||
stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: opts.RepoPath})
|
||||
stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: opts.RepoPath})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -207,7 +208,7 @@ func (c *Commit) HasPreviousCommit(objectID ObjectID) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
_, _, err := NewCommand("merge-base", "--is-ancestor").AddDynamicArguments(that, this).RunStdString(c.repo.Ctx, &RunOpts{Dir: c.repo.Path})
|
||||
_, _, err := gitcmd.NewCommand("merge-base", "--is-ancestor").AddDynamicArguments(that, this).RunStdString(c.repo.Ctx, &gitcmd.RunOpts{Dir: c.repo.Path})
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
@ -348,12 +349,12 @@ func (c *Commit) GetFileContent(filename string, limit int) (string, error) {
|
||||
|
||||
// GetBranchName gets the closest branch name (as returned by 'git name-rev --name-only')
|
||||
func (c *Commit) GetBranchName() (string, error) {
|
||||
cmd := NewCommand("name-rev")
|
||||
cmd := gitcmd.NewCommand("name-rev")
|
||||
if DefaultFeatures().CheckVersionAtLeast("2.13.0") {
|
||||
cmd.AddArguments("--exclude", "refs/tags/*")
|
||||
}
|
||||
cmd.AddArguments("--name-only", "--no-undefined").AddDynamicArguments(c.ID.String())
|
||||
data, _, err := cmd.RunStdString(c.repo.Ctx, &RunOpts{Dir: c.repo.Path})
|
||||
data, _, err := cmd.RunStdString(c.repo.Ctx, &gitcmd.RunOpts{Dir: c.repo.Path})
|
||||
if err != nil {
|
||||
// handle special case where git can not describe commit
|
||||
if strings.Contains(err.Error(), "cannot describe") {
|
||||
@ -431,14 +432,14 @@ func GetCommitFileStatus(ctx context.Context, repoPath, commitID string) (*Commi
|
||||
}()
|
||||
|
||||
stderr := new(bytes.Buffer)
|
||||
err := NewCommand("log", "--name-status", "-m", "--pretty=format:", "--first-parent", "--no-renames", "-z", "-1").AddDynamicArguments(commitID).Run(ctx, &RunOpts{
|
||||
err := gitcmd.NewCommand("log", "--name-status", "-m", "--pretty=format:", "--first-parent", "--no-renames", "-z", "-1").AddDynamicArguments(commitID).Run(ctx, &gitcmd.RunOpts{
|
||||
Dir: repoPath,
|
||||
Stdout: w,
|
||||
Stderr: stderr,
|
||||
})
|
||||
w.Close() // Close writer to exit parsing goroutine
|
||||
if err != nil {
|
||||
return nil, ConcatenateError(err, stderr.String())
|
||||
return nil, gitcmd.ConcatenateError(err, stderr.String())
|
||||
}
|
||||
|
||||
<-done
|
||||
@ -447,7 +448,7 @@ func GetCommitFileStatus(ctx context.Context, repoPath, commitID string) (*Commi
|
||||
|
||||
// GetFullCommitID returns full length (40) of commit ID by given short SHA in a repository.
|
||||
func GetFullCommitID(ctx context.Context, repoPath, shortID string) (string, error) {
|
||||
commitID, _, err := NewCommand("rev-parse").AddDynamicArguments(shortID).RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
commitID, _, err := gitcmd.NewCommand("rev-parse").AddDynamicArguments(shortID).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "exit status 128") {
|
||||
return "", ErrNotExist{shortID, ""}
|
||||
|
||||
@ -11,13 +11,14 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
// syncGitConfig only modifies gitconfig, won't change global variables (otherwise there will be data-race problem)
|
||||
func syncGitConfig(ctx context.Context) (err error) {
|
||||
if err = os.MkdirAll(HomeDir(), os.ModePerm); err != nil {
|
||||
return fmt.Errorf("unable to prepare git home directory %s, err: %w", HomeDir(), err)
|
||||
if err = os.MkdirAll(gitcmd.HomeDir(), os.ModePerm); err != nil {
|
||||
return fmt.Errorf("unable to prepare git home directory %s, err: %w", gitcmd.HomeDir(), err)
|
||||
}
|
||||
|
||||
// first, write user's git config options to git config file
|
||||
@ -117,8 +118,8 @@ func syncGitConfig(ctx context.Context) (err error) {
|
||||
}
|
||||
|
||||
func configSet(ctx context.Context, key, value string) error {
|
||||
stdout, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil)
|
||||
if err != nil && !IsErrorExitCode(err, 1) {
|
||||
stdout, _, err := gitcmd.NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil)
|
||||
if err != nil && !gitcmd.IsErrorExitCode(err, 1) {
|
||||
return fmt.Errorf("failed to get git config %s, err: %w", key, err)
|
||||
}
|
||||
|
||||
@ -127,7 +128,7 @@ func configSet(ctx context.Context, key, value string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, _, err = NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(ctx, nil)
|
||||
_, _, err = gitcmd.NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(ctx, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set git global config %s, err: %w", key, err)
|
||||
}
|
||||
@ -136,14 +137,14 @@ func configSet(ctx context.Context, key, value string) error {
|
||||
}
|
||||
|
||||
func configSetNonExist(ctx context.Context, key, value string) error {
|
||||
_, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil)
|
||||
_, _, err := gitcmd.NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil)
|
||||
if err == nil {
|
||||
// already exist
|
||||
return nil
|
||||
}
|
||||
if IsErrorExitCode(err, 1) {
|
||||
if gitcmd.IsErrorExitCode(err, 1) {
|
||||
// not exist, set new config
|
||||
_, _, err = NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(ctx, nil)
|
||||
_, _, err = gitcmd.NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(ctx, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set git global config %s, err: %w", key, err)
|
||||
}
|
||||
@ -154,14 +155,14 @@ func configSetNonExist(ctx context.Context, key, value string) error {
|
||||
}
|
||||
|
||||
func configAddNonExist(ctx context.Context, key, value string) error {
|
||||
_, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(ctx, nil)
|
||||
_, _, err := gitcmd.NewCommand("config", "--global", "--get").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(ctx, nil)
|
||||
if err == nil {
|
||||
// already exist
|
||||
return nil
|
||||
}
|
||||
if IsErrorExitCode(err, 1) {
|
||||
if gitcmd.IsErrorExitCode(err, 1) {
|
||||
// not exist, add new config
|
||||
_, _, err = NewCommand("config", "--global", "--add").AddDynamicArguments(key, value).RunStdString(ctx, nil)
|
||||
_, _, err = gitcmd.NewCommand("config", "--global", "--add").AddDynamicArguments(key, value).RunStdString(ctx, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add git global config %s, err: %w", key, err)
|
||||
}
|
||||
@ -171,16 +172,16 @@ func configAddNonExist(ctx context.Context, key, value string) error {
|
||||
}
|
||||
|
||||
func configUnsetAll(ctx context.Context, key, value string) error {
|
||||
_, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil)
|
||||
_, _, err := gitcmd.NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil)
|
||||
if err == nil {
|
||||
// exist, need to remove
|
||||
_, _, err = NewCommand("config", "--global", "--unset-all").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(ctx, nil)
|
||||
_, _, err = gitcmd.NewCommand("config", "--global", "--unset-all").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(ctx, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unset git global config %s, err: %w", key, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if IsErrorExitCode(err, 1) {
|
||||
if gitcmd.IsErrorExitCode(err, 1) {
|
||||
// not exist
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -8,13 +8,14 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func gitConfigContains(sub string) bool {
|
||||
if b, err := os.ReadFile(HomeDir() + "/.gitconfig"); err == nil {
|
||||
if b, err := os.ReadFile(gitcmd.HomeDir() + "/.gitconfig"); err == nil {
|
||||
return strings.Contains(string(b), sub)
|
||||
}
|
||||
return false
|
||||
|
||||
@ -14,6 +14,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
@ -34,8 +35,8 @@ func GetRawDiff(repo *Repository, commitID string, diffType RawDiffType, writer
|
||||
// GetReverseRawDiff dumps the reverse diff results of repository in given commit ID to io.Writer.
|
||||
func GetReverseRawDiff(ctx context.Context, repoPath, commitID string, writer io.Writer) error {
|
||||
stderr := new(bytes.Buffer)
|
||||
cmd := NewCommand("show", "--pretty=format:revert %H%n", "-R").AddDynamicArguments(commitID)
|
||||
if err := cmd.Run(ctx, &RunOpts{
|
||||
cmd := gitcmd.NewCommand("show", "--pretty=format:revert %H%n", "-R").AddDynamicArguments(commitID)
|
||||
if err := cmd.Run(ctx, &gitcmd.RunOpts{
|
||||
Dir: repoPath,
|
||||
Stdout: writer,
|
||||
Stderr: stderr,
|
||||
@ -56,7 +57,7 @@ func GetRepoRawDiffForFile(repo *Repository, startCommit, endCommit string, diff
|
||||
files = append(files, file)
|
||||
}
|
||||
|
||||
cmd := NewCommand()
|
||||
cmd := gitcmd.NewCommand()
|
||||
switch diffType {
|
||||
case RawDiffNormal:
|
||||
if len(startCommit) != 0 {
|
||||
@ -89,7 +90,7 @@ func GetRepoRawDiffForFile(repo *Repository, startCommit, endCommit string, diff
|
||||
}
|
||||
|
||||
stderr := new(bytes.Buffer)
|
||||
if err = cmd.Run(repo.Ctx, &RunOpts{
|
||||
if err = cmd.Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: writer,
|
||||
Stderr: stderr,
|
||||
@ -312,8 +313,8 @@ func GetAffectedFiles(repo *Repository, branchName, oldCommitID, newCommitID str
|
||||
affectedFiles := make([]string, 0, 32)
|
||||
|
||||
// Run `git diff --name-only` to get the names of the changed files
|
||||
err = NewCommand("diff", "--name-only").AddDynamicArguments(oldCommitID, newCommitID).
|
||||
Run(repo.Ctx, &RunOpts{
|
||||
err = gitcmd.NewCommand("diff", "--name-only").AddDynamicArguments(oldCommitID, newCommitID).
|
||||
Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Env: env,
|
||||
Dir: repo.Path,
|
||||
Stdout: stdoutWriter,
|
||||
|
||||
@ -9,12 +9,12 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
@ -33,10 +33,7 @@ type Features struct {
|
||||
SupportCheckAttrOnBare bool // >= 2.40
|
||||
}
|
||||
|
||||
var (
|
||||
GitExecutable = "git" // the command name of git, will be updated to an absolute path during initialization
|
||||
defaultFeatures *Features
|
||||
)
|
||||
var defaultFeatures *Features
|
||||
|
||||
func (f *Features) CheckVersionAtLeast(atLeast string) bool {
|
||||
return f.gitVersion.Compare(version.Must(version.NewVersion(atLeast))) >= 0
|
||||
@ -60,7 +57,7 @@ func DefaultFeatures() *Features {
|
||||
}
|
||||
|
||||
func loadGitVersionFeatures() (*Features, error) {
|
||||
stdout, _, runErr := NewCommand("version").RunStdString(context.Background(), nil)
|
||||
stdout, _, runErr := gitcmd.NewCommand("version").RunStdString(context.Background(), nil)
|
||||
if runErr != nil {
|
||||
return nil, runErr
|
||||
}
|
||||
@ -129,32 +126,6 @@ func ensureGitVersion() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetExecutablePath changes the path of git executable and checks the file permission and version.
|
||||
func SetExecutablePath(path string) error {
|
||||
// If path is empty, we use the default value of GitExecutable "git" to search for the location of git.
|
||||
if path != "" {
|
||||
GitExecutable = path
|
||||
}
|
||||
absPath, err := exec.LookPath(GitExecutable)
|
||||
if err != nil {
|
||||
return fmt.Errorf("git not found: %w", err)
|
||||
}
|
||||
GitExecutable = absPath
|
||||
return nil
|
||||
}
|
||||
|
||||
// HomeDir is the home dir for git to store the global config file used by Gitea internally
|
||||
func HomeDir() string {
|
||||
if setting.Git.HomePath == "" {
|
||||
// strict check, make sure the git module is initialized correctly.
|
||||
// attention: when the git module is called in gitea sub-command (serv/hook), the log module might not obviously show messages to users/developers.
|
||||
// for example: if there is gitea git hook code calling git.NewCommand before git.InitXxx, the integration test won't show the real failure reasons.
|
||||
log.Fatal("Unable to init Git's HomeDir, incorrect initialization of the setting and git modules")
|
||||
return ""
|
||||
}
|
||||
return setting.Git.HomePath
|
||||
}
|
||||
|
||||
// InitSimple initializes git module with a very simple step, no config changes, no global command arguments.
|
||||
// This method doesn't change anything to filesystem. At the moment, it is only used by some Gitea sub-commands.
|
||||
func InitSimple() error {
|
||||
@ -167,10 +138,10 @@ func InitSimple() error {
|
||||
}
|
||||
|
||||
if setting.Git.Timeout.Default > 0 {
|
||||
defaultCommandExecutionTimeout = time.Duration(setting.Git.Timeout.Default) * time.Second
|
||||
gitcmd.SetDefaultCommandExecutionTimeout(time.Duration(setting.Git.Timeout.Default) * time.Second)
|
||||
}
|
||||
|
||||
if err := SetExecutablePath(setting.Git.Path); err != nil {
|
||||
if err := gitcmd.SetExecutablePath(setting.Git.Path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -185,7 +156,7 @@ func InitSimple() error {
|
||||
|
||||
// when git works with gnupg (commit signing), there should be a stable home for gnupg commands
|
||||
if _, ok := os.LookupEnv("GNUPGHOME"); !ok {
|
||||
_ = os.Setenv("GNUPGHOME", filepath.Join(HomeDir(), ".gnupg"))
|
||||
_ = os.Setenv("GNUPGHOME", filepath.Join(gitcmd.HomeDir(), ".gnupg"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package git
|
||||
package gitcmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -32,6 +32,10 @@ type TrustedCmdArgs []internal.CmdArg
|
||||
// defaultCommandExecutionTimeout default command execution timeout duration
|
||||
var defaultCommandExecutionTimeout = 360 * time.Second
|
||||
|
||||
func SetDefaultCommandExecutionTimeout(timeout time.Duration) {
|
||||
defaultCommandExecutionTimeout = timeout
|
||||
}
|
||||
|
||||
// DefaultLocale is the default LC_ALL to run git commands in.
|
||||
const DefaultLocale = "C"
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
//go:build race
|
||||
|
||||
package git
|
||||
package gitcmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -1,14 +1,30 @@
|
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package git
|
||||
package gitcmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/tempdir"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
gitHomePath, cleanup, err := tempdir.OsTempDir("gitea-test").MkdirTempRandom("git-home")
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "unable to create temp dir: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
setting.Git.HomePath = gitHomePath
|
||||
}
|
||||
|
||||
func TestRunWithContextStd(t *testing.T) {
|
||||
cmd := NewCommand("--version")
|
||||
stdout, stderr, err := cmd.RunStdString(t.Context(), &RunOpts{})
|
||||
40
modules/git/gitcmd/env.go
Normal file
40
modules/git/gitcmd/env.go
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package gitcmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
var GitExecutable = "git" // the command name of git, will be updated to an absolute path during initialization
|
||||
|
||||
// SetExecutablePath changes the path of git executable and checks the file permission and version.
|
||||
func SetExecutablePath(path string) error {
|
||||
// If path is empty, we use the default value of GitExecutable "git" to search for the location of git.
|
||||
if path != "" {
|
||||
GitExecutable = path
|
||||
}
|
||||
absPath, err := exec.LookPath(GitExecutable)
|
||||
if err != nil {
|
||||
return fmt.Errorf("git not found: %w", err)
|
||||
}
|
||||
GitExecutable = absPath
|
||||
return nil
|
||||
}
|
||||
|
||||
// HomeDir is the home dir for git to store the global config file used by Gitea internally
|
||||
func HomeDir() string {
|
||||
if setting.Git.HomePath == "" {
|
||||
// strict check, make sure the git module is initialized correctly.
|
||||
// attention: when the git module is called in gitea sub-command (serv/hook), the log module might not obviously show messages to users/developers.
|
||||
// for example: if there is gitea git hook code calling NewCommand before git.InitXxx, the integration test won't show the real failure reasons.
|
||||
log.Fatal("Unable to init Git's HomeDir, incorrect initialization of the setting and git modules")
|
||||
return ""
|
||||
}
|
||||
return setting.Git.HomePath
|
||||
}
|
||||
14
modules/git/gitcmd/utils.go
Normal file
14
modules/git/gitcmd/utils.go
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package gitcmd
|
||||
|
||||
import "fmt"
|
||||
|
||||
// ConcatenateError concatenats an error with stderr string
|
||||
func ConcatenateError(err error, stderr string) error {
|
||||
if len(stderr) == 0 {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("%w - %s", err, stderr)
|
||||
}
|
||||
@ -14,6 +14,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
@ -60,7 +61,7 @@ func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepO
|
||||
2^@repo: go-gitea/gitea
|
||||
*/
|
||||
var results []*GrepResult
|
||||
cmd := NewCommand("grep", "--null", "--break", "--heading", "--line-number", "--full-name")
|
||||
cmd := gitcmd.NewCommand("grep", "--null", "--break", "--heading", "--line-number", "--full-name")
|
||||
cmd.AddOptionValues("--context", strconv.Itoa(opts.ContextLineNumber))
|
||||
switch opts.GrepMode {
|
||||
case GrepModeExact:
|
||||
@ -83,7 +84,7 @@ func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepO
|
||||
cmd.AddDashesAndList(opts.PathspecList...)
|
||||
opts.MaxResultLimit = util.IfZero(opts.MaxResultLimit, 50)
|
||||
stderr := bytes.Buffer{}
|
||||
err = cmd.Run(ctx, &RunOpts{
|
||||
err = cmd.Run(ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: stdoutWriter,
|
||||
Stderr: &stderr,
|
||||
@ -135,11 +136,11 @@ func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepO
|
||||
},
|
||||
})
|
||||
// git grep exits by cancel (killed), usually it is caused by the limit of results
|
||||
if IsErrorExitCode(err, -1) && stderr.Len() == 0 {
|
||||
if gitcmd.IsErrorExitCode(err, -1) && stderr.Len() == 0 {
|
||||
return results, nil
|
||||
}
|
||||
// git grep exits with 1 if no results are found
|
||||
if IsErrorExitCode(err, 1) && stderr.Len() == 0 {
|
||||
if gitcmd.IsErrorExitCode(err, 1) && stderr.Len() == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil && !errors.Is(err, context.Canceled) {
|
||||
|
||||
@ -3,13 +3,24 @@
|
||||
|
||||
package git
|
||||
|
||||
import "code.gitea.io/gitea/modules/setting"
|
||||
|
||||
// Based on https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgformat
|
||||
const (
|
||||
SigningKeyFormatOpenPGP = "openpgp" // for GPG keys, the expected default of git cli
|
||||
SigningKeyFormatSSH = "ssh"
|
||||
)
|
||||
|
||||
// SigningKey represents an instance key info which will be used to sign git commits.
|
||||
// FIXME: need to refactor it to a new name, this name conflicts with the variable names for "asymkey.GPGKey" in many places.
|
||||
type SigningKey struct {
|
||||
KeyID string
|
||||
Format string
|
||||
}
|
||||
|
||||
func (s *SigningKey) String() string {
|
||||
// Do not expose KeyID
|
||||
// In case the key is a file path and the struct is rendered in a template, then the server path will be exposed.
|
||||
setting.PanicInDevOrTesting("don't call SigningKey.String() - it exposes the KeyID which might be a local file path")
|
||||
return "SigningKey:" + s.Format
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
|
||||
"github.com/djherbis/buffer"
|
||||
"github.com/djherbis/nio/v3"
|
||||
@ -34,7 +35,7 @@ func LogNameStatusRepo(ctx context.Context, repository, head, treepath string, p
|
||||
_ = stdoutWriter.Close()
|
||||
}
|
||||
|
||||
cmd := NewCommand()
|
||||
cmd := gitcmd.NewCommand()
|
||||
cmd.AddArguments("log", "--name-status", "-c", "--format=commit%x00%H %P%x00", "--parents", "--no-renames", "-t", "-z").AddDynamicArguments(head)
|
||||
|
||||
var files []string
|
||||
@ -64,13 +65,13 @@ func LogNameStatusRepo(ctx context.Context, repository, head, treepath string, p
|
||||
|
||||
go func() {
|
||||
stderr := strings.Builder{}
|
||||
err := cmd.Run(ctx, &RunOpts{
|
||||
err := cmd.Run(ctx, &gitcmd.RunOpts{
|
||||
Dir: repository,
|
||||
Stdout: stdoutWriter,
|
||||
Stderr: &stderr,
|
||||
})
|
||||
if err != nil {
|
||||
_ = stdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
|
||||
_ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String()))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
@ -25,8 +25,8 @@ func CatFileBatchCheck(ctx context.Context, shasToCheckReader *io.PipeReader, ca
|
||||
|
||||
stderr := new(bytes.Buffer)
|
||||
var errbuf strings.Builder
|
||||
cmd := git.NewCommand("cat-file", "--batch-check")
|
||||
if err := cmd.Run(ctx, &git.RunOpts{
|
||||
cmd := gitcmd.NewCommand("cat-file", "--batch-check")
|
||||
if err := cmd.Run(ctx, &gitcmd.RunOpts{
|
||||
Dir: tmpBasePath,
|
||||
Stdin: shasToCheckReader,
|
||||
Stdout: catFileCheckWriter,
|
||||
@ -43,8 +43,8 @@ func CatFileBatchCheckAllObjects(ctx context.Context, catFileCheckWriter *io.Pip
|
||||
|
||||
stderr := new(bytes.Buffer)
|
||||
var errbuf strings.Builder
|
||||
cmd := git.NewCommand("cat-file", "--batch-check", "--batch-all-objects")
|
||||
if err := cmd.Run(ctx, &git.RunOpts{
|
||||
cmd := gitcmd.NewCommand("cat-file", "--batch-check", "--batch-all-objects")
|
||||
if err := cmd.Run(ctx, &gitcmd.RunOpts{
|
||||
Dir: tmpBasePath,
|
||||
Stdout: catFileCheckWriter,
|
||||
Stderr: stderr,
|
||||
@ -64,7 +64,7 @@ func CatFileBatch(ctx context.Context, shasToBatchReader *io.PipeReader, catFile
|
||||
|
||||
stderr := new(bytes.Buffer)
|
||||
var errbuf strings.Builder
|
||||
if err := git.NewCommand("cat-file", "--batch").Run(ctx, &git.RunOpts{
|
||||
if err := gitcmd.NewCommand("cat-file", "--batch").Run(ctx, &gitcmd.RunOpts{
|
||||
Dir: tmpBasePath,
|
||||
Stdout: catFileBatchWriter,
|
||||
Stdin: shasToBatchReader,
|
||||
|
||||
@ -14,6 +14,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// FindLFSFile finds commits that contain a provided pointer file hash
|
||||
@ -32,13 +33,13 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
|
||||
|
||||
go func() {
|
||||
stderr := strings.Builder{}
|
||||
err := git.NewCommand("rev-list", "--all").Run(repo.Ctx, &git.RunOpts{
|
||||
err := gitcmd.NewCommand("rev-list", "--all").Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: revListWriter,
|
||||
Stderr: &stderr,
|
||||
})
|
||||
if err != nil {
|
||||
_ = revListWriter.CloseWithError(git.ConcatenateError(err, (&stderr).String()))
|
||||
_ = revListWriter.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String()))
|
||||
} else {
|
||||
_ = revListWriter.Close()
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// NameRevStdin runs name-rev --stdin
|
||||
@ -22,7 +22,7 @@ func NameRevStdin(ctx context.Context, shasToNameReader *io.PipeReader, nameRevS
|
||||
|
||||
stderr := new(bytes.Buffer)
|
||||
var errbuf strings.Builder
|
||||
if err := git.NewCommand("name-rev", "--stdin", "--name-only", "--always").Run(ctx, &git.RunOpts{
|
||||
if err := gitcmd.NewCommand("name-rev", "--stdin", "--name-only", "--always").Run(ctx, &gitcmd.RunOpts{
|
||||
Dir: tmpBasePath,
|
||||
Stdout: nameRevStdinWriter,
|
||||
Stdin: shasToNameReader,
|
||||
|
||||
@ -12,7 +12,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
@ -23,8 +23,8 @@ func RevListAllObjects(ctx context.Context, revListWriter *io.PipeWriter, wg *sy
|
||||
|
||||
stderr := new(bytes.Buffer)
|
||||
var errbuf strings.Builder
|
||||
cmd := git.NewCommand("rev-list", "--objects", "--all")
|
||||
if err := cmd.Run(ctx, &git.RunOpts{
|
||||
cmd := gitcmd.NewCommand("rev-list", "--objects", "--all")
|
||||
if err := cmd.Run(ctx, &gitcmd.RunOpts{
|
||||
Dir: basePath,
|
||||
Stdout: revListWriter,
|
||||
Stderr: stderr,
|
||||
@ -42,11 +42,11 @@ func RevListObjects(ctx context.Context, revListWriter *io.PipeWriter, wg *sync.
|
||||
defer revListWriter.Close()
|
||||
stderr := new(bytes.Buffer)
|
||||
var errbuf strings.Builder
|
||||
cmd := git.NewCommand("rev-list", "--objects").AddDynamicArguments(headSHA)
|
||||
cmd := gitcmd.NewCommand("rev-list", "--objects").AddDynamicArguments(headSHA)
|
||||
if baseSHA != "" {
|
||||
cmd = cmd.AddArguments("--not").AddDynamicArguments(baseSHA)
|
||||
}
|
||||
if err := cmd.Run(ctx, &git.RunOpts{
|
||||
if err := cmd.Run(ctx, &gitcmd.RunOpts{
|
||||
Dir: tmpBasePath,
|
||||
Stdout: revListWriter,
|
||||
Stderr: stderr,
|
||||
|
||||
@ -9,19 +9,20 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// GetRemoteAddress returns remote url of git repository in the repoPath with special remote name
|
||||
func GetRemoteAddress(ctx context.Context, repoPath, remoteName string) (string, error) {
|
||||
var cmd *Command
|
||||
var cmd *gitcmd.Command
|
||||
if DefaultFeatures().CheckVersionAtLeast("2.7") {
|
||||
cmd = NewCommand("remote", "get-url").AddDynamicArguments(remoteName)
|
||||
cmd = gitcmd.NewCommand("remote", "get-url").AddDynamicArguments(remoteName)
|
||||
} else {
|
||||
cmd = NewCommand("config", "--get").AddDynamicArguments("remote." + remoteName + ".url")
|
||||
cmd = gitcmd.NewCommand("config", "--get").AddDynamicArguments("remote." + remoteName + ".url")
|
||||
}
|
||||
|
||||
result, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
result, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/proxy"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
@ -40,9 +41,9 @@ func (repo *Repository) GetAllCommitsCount() (int64, error) {
|
||||
|
||||
func (repo *Repository) ShowPrettyFormatLogToList(ctx context.Context, revisionRange string) ([]*Commit, error) {
|
||||
// avoid: ambiguous argument 'refs/a...refs/b': unknown revision or path not in the working tree. Use '--': 'git <command> [<revision>...] -- [<file>...]'
|
||||
logs, _, err := NewCommand("log").AddArguments(prettyLogFormat).
|
||||
logs, _, err := gitcmd.NewCommand("log").AddArguments(prettyLogFormat).
|
||||
AddDynamicArguments(revisionRange).AddArguments("--").
|
||||
RunStdBytes(ctx, &RunOpts{Dir: repo.Path})
|
||||
RunStdBytes(ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -70,7 +71,7 @@ func (repo *Repository) parsePrettyFormatLogToList(logs []byte) ([]*Commit, erro
|
||||
|
||||
// IsRepoURLAccessible checks if given repository URL is accessible.
|
||||
func IsRepoURLAccessible(ctx context.Context, url string) bool {
|
||||
_, _, err := NewCommand("ls-remote", "-q", "-h").AddDynamicArguments(url, "HEAD").RunStdString(ctx, nil)
|
||||
_, _, err := gitcmd.NewCommand("ls-remote", "-q", "-h").AddDynamicArguments(url, "HEAD").RunStdString(ctx, nil)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
@ -81,7 +82,7 @@ func InitRepository(ctx context.Context, repoPath string, bare bool, objectForma
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := NewCommand("init")
|
||||
cmd := gitcmd.NewCommand("init")
|
||||
|
||||
if !IsValidObjectFormat(objectFormatName) {
|
||||
return fmt.Errorf("invalid object format: %s", objectFormatName)
|
||||
@ -93,15 +94,15 @@ func InitRepository(ctx context.Context, repoPath string, bare bool, objectForma
|
||||
if bare {
|
||||
cmd.AddArguments("--bare")
|
||||
}
|
||||
_, _, err = cmd.RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
_, _, err = cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
return err
|
||||
}
|
||||
|
||||
// IsEmpty Check if repository is empty.
|
||||
func (repo *Repository) IsEmpty() (bool, error) {
|
||||
var errbuf, output strings.Builder
|
||||
if err := NewCommand().AddOptionFormat("--git-dir=%s", repo.Path).AddArguments("rev-list", "-n", "1", "--all").
|
||||
Run(repo.Ctx, &RunOpts{
|
||||
if err := gitcmd.NewCommand().AddOptionFormat("--git-dir=%s", repo.Path).AddArguments("rev-list", "-n", "1", "--all").
|
||||
Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: &output,
|
||||
Stderr: &errbuf,
|
||||
@ -137,7 +138,7 @@ func Clone(ctx context.Context, from, to string, opts CloneRepoOptions) error {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := NewCommand().AddArguments("clone")
|
||||
cmd := gitcmd.NewCommand().AddArguments("clone")
|
||||
if opts.SkipTLSVerify {
|
||||
cmd.AddArguments("-c", "http.sslVerify=false")
|
||||
}
|
||||
@ -178,13 +179,13 @@ func Clone(ctx context.Context, from, to string, opts CloneRepoOptions) error {
|
||||
}
|
||||
|
||||
stderr := new(bytes.Buffer)
|
||||
if err = cmd.Run(ctx, &RunOpts{
|
||||
if err = cmd.Run(ctx, &gitcmd.RunOpts{
|
||||
Timeout: opts.Timeout,
|
||||
Env: envs,
|
||||
Stdout: io.Discard,
|
||||
Stderr: stderr,
|
||||
}); err != nil {
|
||||
return ConcatenateError(err, stderr.String())
|
||||
return gitcmd.ConcatenateError(err, stderr.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -201,7 +202,7 @@ type PushOptions struct {
|
||||
|
||||
// Push pushs local commits to given remote branch.
|
||||
func Push(ctx context.Context, repoPath string, opts PushOptions) error {
|
||||
cmd := NewCommand("push")
|
||||
cmd := gitcmd.NewCommand("push")
|
||||
if opts.Force {
|
||||
cmd.AddArguments("-f")
|
||||
}
|
||||
@ -214,7 +215,7 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error {
|
||||
}
|
||||
cmd.AddDashesAndList(remoteBranchArgs...)
|
||||
|
||||
stdout, stderr, err := cmd.RunStdString(ctx, &RunOpts{Env: opts.Env, Timeout: opts.Timeout, Dir: repoPath})
|
||||
stdout, stderr, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Env: opts.Env, Timeout: opts.Timeout, Dir: repoPath})
|
||||
if err != nil {
|
||||
if strings.Contains(stderr, "non-fast-forward") {
|
||||
return &ErrPushOutOfDate{StdOut: stdout, StdErr: stderr, Err: err}
|
||||
@ -233,8 +234,8 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error {
|
||||
|
||||
// GetLatestCommitTime returns time for latest commit in repository (across all branches)
|
||||
func GetLatestCommitTime(ctx context.Context, repoPath string) (time.Time, error) {
|
||||
cmd := NewCommand("for-each-ref", "--sort=-committerdate", BranchPrefix, "--count", "1", "--format=%(committerdate)")
|
||||
stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
cmd := gitcmd.NewCommand("for-each-ref", "--sort=-committerdate", BranchPrefix, "--count", "1", "--format=%(committerdate)")
|
||||
stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
@ -250,9 +251,9 @@ type DivergeObject struct {
|
||||
|
||||
// GetDivergingCommits returns the number of commits a targetBranch is ahead or behind a baseBranch
|
||||
func GetDivergingCommits(ctx context.Context, repoPath, baseBranch, targetBranch string) (do DivergeObject, err error) {
|
||||
cmd := NewCommand("rev-list", "--count", "--left-right").
|
||||
cmd := gitcmd.NewCommand("rev-list", "--count", "--left-right").
|
||||
AddDynamicArguments(baseBranch + "..." + targetBranch).AddArguments("--")
|
||||
stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
return do, err
|
||||
}
|
||||
@ -281,23 +282,23 @@ func (repo *Repository) CreateBundle(ctx context.Context, commit string, out io.
|
||||
defer cleanup()
|
||||
|
||||
env := append(os.Environ(), "GIT_OBJECT_DIRECTORY="+filepath.Join(repo.Path, "objects"))
|
||||
_, _, err = NewCommand("init", "--bare").RunStdString(ctx, &RunOpts{Dir: tmp, Env: env})
|
||||
_, _, err = gitcmd.NewCommand("init", "--bare").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = NewCommand("reset", "--soft").AddDynamicArguments(commit).RunStdString(ctx, &RunOpts{Dir: tmp, Env: env})
|
||||
_, _, err = gitcmd.NewCommand("reset", "--soft").AddDynamicArguments(commit).RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = NewCommand("branch", "-m", "bundle").RunStdString(ctx, &RunOpts{Dir: tmp, Env: env})
|
||||
_, _, err = gitcmd.NewCommand("branch", "-m", "bundle").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tmpFile := filepath.Join(tmp, "bundle")
|
||||
_, _, err = NewCommand("bundle", "create").AddDynamicArguments(tmpFile, "bundle", "HEAD").RunStdString(ctx, &RunOpts{Dir: tmp, Env: env})
|
||||
_, _, err = gitcmd.NewCommand("bundle", "create").AddDynamicArguments(tmpFile, "bundle", "HEAD").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -10,6 +10,8 @@ import (
|
||||
"io"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// ArchiveType archive types
|
||||
@ -53,7 +55,7 @@ func (repo *Repository) CreateArchive(ctx context.Context, format ArchiveType, t
|
||||
return fmt.Errorf("unknown format: %v", format)
|
||||
}
|
||||
|
||||
cmd := NewCommand("archive")
|
||||
cmd := gitcmd.NewCommand("archive")
|
||||
if usePrefix {
|
||||
cmd.AddOptionFormat("--prefix=%s", filepath.Base(strings.TrimSuffix(repo.Path, ".git"))+"/")
|
||||
}
|
||||
@ -61,13 +63,13 @@ func (repo *Repository) CreateArchive(ctx context.Context, format ArchiveType, t
|
||||
cmd.AddDynamicArguments(commitID)
|
||||
|
||||
var stderr strings.Builder
|
||||
err := cmd.Run(ctx, &RunOpts{
|
||||
err := cmd.Run(ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: target,
|
||||
Stderr: &stderr,
|
||||
})
|
||||
if err != nil {
|
||||
return ConcatenateError(err, stderr.String())
|
||||
return gitcmd.ConcatenateError(err, stderr.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -5,14 +5,16 @@ package git
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// LineBlame returns the latest commit at the given line
|
||||
func (repo *Repository) LineBlame(revision, path, file string, line uint) (*Commit, error) {
|
||||
res, _, err := NewCommand("blame").
|
||||
res, _, err := gitcmd.NewCommand("blame").
|
||||
AddOptionFormat("-L %d,%d", line, line).
|
||||
AddOptionValues("-p", revision).
|
||||
AddDashesAndList(file).RunStdString(repo.Ctx, &RunOpts{Dir: path})
|
||||
AddDashesAndList(file).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -8,6 +8,8 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// BranchPrefix base dir of the branch information file store on git
|
||||
@ -15,7 +17,7 @@ const BranchPrefix = "refs/heads/"
|
||||
|
||||
// IsReferenceExist returns true if given reference exists in the repository.
|
||||
func IsReferenceExist(ctx context.Context, repoPath, name string) bool {
|
||||
_, _, err := NewCommand("show-ref", "--verify").AddDashesAndList(name).RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
_, _, err := gitcmd.NewCommand("show-ref", "--verify").AddDashesAndList(name).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
return err == nil
|
||||
}
|
||||
|
||||
@ -25,7 +27,7 @@ func IsBranchExist(ctx context.Context, repoPath, name string) bool {
|
||||
}
|
||||
|
||||
func GetDefaultBranch(ctx context.Context, repoPath string) (string, error) {
|
||||
stdout, _, err := NewCommand("symbolic-ref", "HEAD").RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
stdout, _, err := gitcmd.NewCommand("symbolic-ref", "HEAD").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -43,7 +45,7 @@ type DeleteBranchOptions struct {
|
||||
|
||||
// DeleteBranch delete a branch by name on repository.
|
||||
func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) error {
|
||||
cmd := NewCommand("branch")
|
||||
cmd := gitcmd.NewCommand("branch")
|
||||
|
||||
if opts.Force {
|
||||
cmd.AddArguments("-D")
|
||||
@ -52,35 +54,35 @@ func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) erro
|
||||
}
|
||||
|
||||
cmd.AddDashesAndList(name)
|
||||
_, _, err := cmd.RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
_, _, err := cmd.RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateBranch create a new branch
|
||||
func (repo *Repository) CreateBranch(branch, oldbranchOrCommit string) error {
|
||||
cmd := NewCommand("branch")
|
||||
cmd := gitcmd.NewCommand("branch")
|
||||
cmd.AddDashesAndList(branch, oldbranchOrCommit)
|
||||
|
||||
_, _, err := cmd.RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
_, _, err := cmd.RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// AddRemote adds a new remote to repository.
|
||||
func (repo *Repository) AddRemote(name, url string, fetch bool) error {
|
||||
cmd := NewCommand("remote", "add")
|
||||
cmd := gitcmd.NewCommand("remote", "add")
|
||||
if fetch {
|
||||
cmd.AddArguments("-f")
|
||||
}
|
||||
cmd.AddDynamicArguments(name, url)
|
||||
|
||||
_, _, err := cmd.RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
_, _, err := cmd.RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
return err
|
||||
}
|
||||
|
||||
// RenameBranch rename a branch
|
||||
func (repo *Repository) RenameBranch(from, to string) error {
|
||||
_, _, err := NewCommand("branch", "-m").AddDynamicArguments(from, to).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
_, _, err := gitcmd.NewCommand("branch", "-m").AddDynamicArguments(from, to).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
@ -70,25 +71,25 @@ func (repo *Repository) IsBranchExist(name string) bool {
|
||||
// GetBranchNames returns branches from the repository, skipping "skip" initial branches and
|
||||
// returning at most "limit" branches, or all branches if "limit" is 0.
|
||||
func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) {
|
||||
return callShowRef(repo.Ctx, repo.Path, BranchPrefix, TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"}, skip, limit)
|
||||
return callShowRef(repo.Ctx, repo.Path, BranchPrefix, gitcmd.TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"}, skip, limit)
|
||||
}
|
||||
|
||||
// WalkReferences walks all the references from the repository
|
||||
// refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty.
|
||||
func (repo *Repository) WalkReferences(refType ObjectType, skip, limit int, walkfn func(sha1, refname string) error) (int, error) {
|
||||
var args TrustedCmdArgs
|
||||
var args gitcmd.TrustedCmdArgs
|
||||
switch refType {
|
||||
case ObjectTag:
|
||||
args = TrustedCmdArgs{TagPrefix, "--sort=-taggerdate"}
|
||||
args = gitcmd.TrustedCmdArgs{TagPrefix, "--sort=-taggerdate"}
|
||||
case ObjectBranch:
|
||||
args = TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"}
|
||||
args = gitcmd.TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"}
|
||||
}
|
||||
|
||||
return WalkShowRef(repo.Ctx, repo.Path, args, skip, limit, walkfn)
|
||||
}
|
||||
|
||||
// callShowRef return refs, if limit = 0 it will not limit
|
||||
func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs TrustedCmdArgs, skip, limit int) (branchNames []string, countAll int, err error) {
|
||||
func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs gitcmd.TrustedCmdArgs, skip, limit int) (branchNames []string, countAll int, err error) {
|
||||
countAll, err = WalkShowRef(ctx, repoPath, extraArgs, skip, limit, func(_, branchName string) error {
|
||||
branchName = strings.TrimPrefix(branchName, trimPrefix)
|
||||
branchNames = append(branchNames, branchName)
|
||||
@ -98,7 +99,7 @@ func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs Tru
|
||||
return branchNames, countAll, err
|
||||
}
|
||||
|
||||
func WalkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) {
|
||||
func WalkShowRef(ctx context.Context, repoPath string, extraArgs gitcmd.TrustedCmdArgs, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) {
|
||||
stdoutReader, stdoutWriter := io.Pipe()
|
||||
defer func() {
|
||||
_ = stdoutReader.Close()
|
||||
@ -107,9 +108,9 @@ func WalkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs,
|
||||
|
||||
go func() {
|
||||
stderrBuilder := &strings.Builder{}
|
||||
args := TrustedCmdArgs{"for-each-ref", "--format=%(objectname) %(refname)"}
|
||||
args := gitcmd.TrustedCmdArgs{"for-each-ref", "--format=%(objectname) %(refname)"}
|
||||
args = append(args, extraArgs...)
|
||||
err := NewCommand(args...).Run(ctx, &RunOpts{
|
||||
err := gitcmd.NewCommand(args...).Run(ctx, &gitcmd.RunOpts{
|
||||
Dir: repoPath,
|
||||
Stdout: stdoutWriter,
|
||||
Stderr: stderrBuilder,
|
||||
@ -119,7 +120,7 @@ func WalkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs,
|
||||
_ = stdoutWriter.Close()
|
||||
return
|
||||
}
|
||||
_ = stdoutWriter.CloseWithError(ConcatenateError(err, stderrBuilder.String()))
|
||||
_ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, stderrBuilder.String()))
|
||||
} else {
|
||||
_ = stdoutWriter.Close()
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
@ -59,7 +60,7 @@ func (repo *Repository) getCommitByPathWithID(id ObjectID, relpath string) (*Com
|
||||
relpath = `\` + relpath
|
||||
}
|
||||
|
||||
stdout, _, runErr := NewCommand("log", "-1", prettyLogFormat).AddDynamicArguments(id.String()).AddDashesAndList(relpath).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, runErr := gitcmd.NewCommand("log", "-1", prettyLogFormat).AddDynamicArguments(id.String()).AddDashesAndList(relpath).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if runErr != nil {
|
||||
return nil, runErr
|
||||
}
|
||||
@ -74,7 +75,7 @@ func (repo *Repository) getCommitByPathWithID(id ObjectID, relpath string) (*Com
|
||||
|
||||
// GetCommitByPath returns the last commit of relative path.
|
||||
func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) {
|
||||
stdout, _, runErr := NewCommand("log", "-1", prettyLogFormat).AddDashesAndList(relpath).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, runErr := gitcmd.NewCommand("log", "-1", prettyLogFormat).AddDashesAndList(relpath).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if runErr != nil {
|
||||
return nil, runErr
|
||||
}
|
||||
@ -91,7 +92,7 @@ func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) {
|
||||
|
||||
// commitsByRangeWithTime returns the specific page commits before current revision, with not, since, until support
|
||||
func (repo *Repository) commitsByRangeWithTime(id ObjectID, page, pageSize int, not, since, until string) ([]*Commit, error) {
|
||||
cmd := NewCommand("log").
|
||||
cmd := gitcmd.NewCommand("log").
|
||||
AddOptionFormat("--skip=%d", (page-1)*pageSize).
|
||||
AddOptionFormat("--max-count=%d", pageSize).
|
||||
AddArguments(prettyLogFormat).
|
||||
@ -107,7 +108,7 @@ func (repo *Repository) commitsByRangeWithTime(id ObjectID, page, pageSize int,
|
||||
cmd.AddOptionFormat("--until=%s", until)
|
||||
}
|
||||
|
||||
stdout, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -117,7 +118,7 @@ func (repo *Repository) commitsByRangeWithTime(id ObjectID, page, pageSize int,
|
||||
|
||||
func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([]*Commit, error) {
|
||||
// add common arguments to git command
|
||||
addCommonSearchArgs := func(c *Command) {
|
||||
addCommonSearchArgs := func(c *gitcmd.Command) {
|
||||
// ignore case
|
||||
c.AddArguments("-i")
|
||||
|
||||
@ -141,7 +142,7 @@ func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([
|
||||
}
|
||||
|
||||
// create new git log command with limit of 100 commits
|
||||
cmd := NewCommand("log", "-100", prettyLogFormat).AddDynamicArguments(id.String())
|
||||
cmd := gitcmd.NewCommand("log", "-100", prettyLogFormat).AddDynamicArguments(id.String())
|
||||
|
||||
// pretend that all refs along with HEAD were listed on command line as <commis>
|
||||
// https://git-scm.com/docs/git-log#Documentation/git-log.txt---all
|
||||
@ -161,7 +162,7 @@ func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([
|
||||
|
||||
// search for commits matching given constraints and keywords in commit msg
|
||||
addCommonSearchArgs(cmd)
|
||||
stdout, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -175,14 +176,14 @@ func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([
|
||||
// ignore anything not matching a valid sha pattern
|
||||
if id.Type().IsValid(v) {
|
||||
// create new git log command with 1 commit limit
|
||||
hashCmd := NewCommand("log", "-1", prettyLogFormat)
|
||||
hashCmd := gitcmd.NewCommand("log", "-1", prettyLogFormat)
|
||||
// add previous arguments except for --grep and --all
|
||||
addCommonSearchArgs(hashCmd)
|
||||
// add keyword as <commit>
|
||||
hashCmd.AddDynamicArguments(v)
|
||||
|
||||
// search with given constraints for commit matching sha hash of v
|
||||
hashMatching, _, err := hashCmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
hashMatching, _, err := hashCmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil || bytes.Contains(stdout, hashMatching) {
|
||||
continue
|
||||
}
|
||||
@ -197,7 +198,7 @@ func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([
|
||||
// FileChangedBetweenCommits Returns true if the file changed between commit IDs id1 and id2
|
||||
// You must ensure that id1 and id2 are valid commit ids.
|
||||
func (repo *Repository) FileChangedBetweenCommits(filename, id1, id2 string) (bool, error) {
|
||||
stdout, _, err := NewCommand("diff", "--name-only", "-z").AddDynamicArguments(id1, id2).AddDashesAndList(filename).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := gitcmd.NewCommand("diff", "--name-only", "-z").AddDynamicArguments(id1, id2).AddDashesAndList(filename).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -232,7 +233,7 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions)
|
||||
}()
|
||||
go func() {
|
||||
stderr := strings.Builder{}
|
||||
gitCmd := NewCommand("rev-list").
|
||||
gitCmd := gitcmd.NewCommand("rev-list").
|
||||
AddOptionFormat("--max-count=%d", setting.Git.CommitsRangeSize).
|
||||
AddOptionFormat("--skip=%d", (opts.Page-1)*setting.Git.CommitsRangeSize)
|
||||
gitCmd.AddDynamicArguments(opts.Revision)
|
||||
@ -248,13 +249,13 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions)
|
||||
}
|
||||
|
||||
gitCmd.AddDashesAndList(opts.File)
|
||||
err := gitCmd.Run(repo.Ctx, &RunOpts{
|
||||
err := gitCmd.Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: stdoutWriter,
|
||||
Stderr: &stderr,
|
||||
})
|
||||
if err != nil {
|
||||
_ = stdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
|
||||
_ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String()))
|
||||
} else {
|
||||
_ = stdoutWriter.Close()
|
||||
}
|
||||
@ -290,11 +291,11 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions)
|
||||
|
||||
// FilesCountBetween return the number of files changed between two commits
|
||||
func (repo *Repository) FilesCountBetween(startCommitID, endCommitID string) (int, error) {
|
||||
stdout, _, err := NewCommand("diff", "--name-only").AddDynamicArguments(startCommitID+"..."+endCommitID).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := gitcmd.NewCommand("diff", "--name-only").AddDynamicArguments(startCommitID+"..."+endCommitID).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil && strings.Contains(err.Error(), "no merge base") {
|
||||
// git >= 2.28 now returns an error if startCommitID and endCommitID have become unrelated.
|
||||
// previously it would return the results of git diff --name-only startCommitID endCommitID so let's try that...
|
||||
stdout, _, err = NewCommand("diff", "--name-only").AddDynamicArguments(startCommitID, endCommitID).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err = gitcmd.NewCommand("diff", "--name-only").AddDynamicArguments(startCommitID, endCommitID).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@ -308,13 +309,13 @@ func (repo *Repository) CommitsBetween(last, before *Commit) ([]*Commit, error)
|
||||
var stdout []byte
|
||||
var err error
|
||||
if before == nil {
|
||||
stdout, _, err = NewCommand("rev-list").AddDynamicArguments(last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
} else {
|
||||
stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil && strings.Contains(err.Error(), "no merge base") {
|
||||
// future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
|
||||
// previously it would return the results of git rev-list before last so let's try that...
|
||||
stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
@ -328,22 +329,22 @@ func (repo *Repository) CommitsBetweenLimit(last, before *Commit, limit, skip in
|
||||
var stdout []byte
|
||||
var err error
|
||||
if before == nil {
|
||||
stdout, _, err = NewCommand("rev-list").
|
||||
stdout, _, err = gitcmd.NewCommand("rev-list").
|
||||
AddOptionValues("--max-count", strconv.Itoa(limit)).
|
||||
AddOptionValues("--skip", strconv.Itoa(skip)).
|
||||
AddDynamicArguments(last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
AddDynamicArguments(last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
} else {
|
||||
stdout, _, err = NewCommand("rev-list").
|
||||
stdout, _, err = gitcmd.NewCommand("rev-list").
|
||||
AddOptionValues("--max-count", strconv.Itoa(limit)).
|
||||
AddOptionValues("--skip", strconv.Itoa(skip)).
|
||||
AddDynamicArguments(before.ID.String()+".."+last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
AddDynamicArguments(before.ID.String()+".."+last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil && strings.Contains(err.Error(), "no merge base") {
|
||||
// future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
|
||||
// previously it would return the results of git rev-list --max-count n before last so let's try that...
|
||||
stdout, _, err = NewCommand("rev-list").
|
||||
stdout, _, err = gitcmd.NewCommand("rev-list").
|
||||
AddOptionValues("--max-count", strconv.Itoa(limit)).
|
||||
AddOptionValues("--skip", strconv.Itoa(skip)).
|
||||
AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
@ -358,13 +359,13 @@ func (repo *Repository) CommitsBetweenNotBase(last, before *Commit, baseBranch s
|
||||
var stdout []byte
|
||||
var err error
|
||||
if before == nil {
|
||||
stdout, _, err = NewCommand("rev-list").AddDynamicArguments(last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
} else {
|
||||
stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil && strings.Contains(err.Error(), "no merge base") {
|
||||
// future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
|
||||
// previously it would return the results of git rev-list before last so let's try that...
|
||||
stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
@ -410,13 +411,13 @@ func (repo *Repository) CommitsCountBetween(start, end string) (int64, error) {
|
||||
|
||||
// commitsBefore the limit is depth, not total number of returned commits.
|
||||
func (repo *Repository) commitsBefore(id ObjectID, limit int) ([]*Commit, error) {
|
||||
cmd := NewCommand("log", prettyLogFormat)
|
||||
cmd := gitcmd.NewCommand("log", prettyLogFormat)
|
||||
if limit > 0 {
|
||||
cmd.AddOptionFormat("-%d", limit)
|
||||
}
|
||||
cmd.AddDynamicArguments(id.String())
|
||||
|
||||
stdout, _, runErr := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, runErr := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if runErr != nil {
|
||||
return nil, runErr
|
||||
}
|
||||
@ -453,10 +454,10 @@ func (repo *Repository) getCommitsBeforeLimit(id ObjectID, num int) ([]*Commit,
|
||||
|
||||
func (repo *Repository) getBranches(env []string, commitID string, limit int) ([]string, error) {
|
||||
if DefaultFeatures().CheckVersionAtLeast("2.7.0") {
|
||||
stdout, _, err := NewCommand("for-each-ref", "--format=%(refname:strip=2)").
|
||||
stdout, _, err := gitcmd.NewCommand("for-each-ref", "--format=%(refname:strip=2)").
|
||||
AddOptionFormat("--count=%d", limit).
|
||||
AddOptionValues("--contains", commitID, BranchPrefix).
|
||||
RunStdString(repo.Ctx, &RunOpts{
|
||||
RunStdString(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Env: env,
|
||||
})
|
||||
@ -468,7 +469,7 @@ func (repo *Repository) getBranches(env []string, commitID string, limit int) ([
|
||||
return branches, nil
|
||||
}
|
||||
|
||||
stdout, _, err := NewCommand("branch").AddOptionValues("--contains", commitID).RunStdString(repo.Ctx, &RunOpts{
|
||||
stdout, _, err := gitcmd.NewCommand("branch").AddOptionValues("--contains", commitID).RunStdString(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Env: env,
|
||||
})
|
||||
@ -510,7 +511,7 @@ func (repo *Repository) GetCommitsFromIDs(commitIDs []string) []*Commit {
|
||||
|
||||
// IsCommitInBranch check if the commit is on the branch
|
||||
func (repo *Repository) IsCommitInBranch(commitID, branch string) (r bool, err error) {
|
||||
stdout, _, err := NewCommand("branch", "--contains").AddDynamicArguments(commitID, branch).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := gitcmd.NewCommand("branch", "--contains").AddDynamicArguments(commitID, branch).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -536,10 +537,10 @@ func (repo *Repository) AddLastCommitCache(cacheKey, fullName, sha string) error
|
||||
|
||||
// GetCommitBranchStart returns the commit where the branch diverged
|
||||
func (repo *Repository) GetCommitBranchStart(env []string, branch, endCommitID string) (string, error) {
|
||||
cmd := NewCommand("log", prettyLogFormat)
|
||||
cmd := gitcmd.NewCommand("log", prettyLogFormat)
|
||||
cmd.AddDynamicArguments(endCommitID)
|
||||
|
||||
stdout, _, runErr := cmd.RunStdBytes(repo.Ctx, &RunOpts{
|
||||
stdout, _, runErr := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Env: env,
|
||||
})
|
||||
|
||||
@ -9,6 +9,8 @@ package git
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/hash"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
@ -59,7 +61,7 @@ func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
|
||||
}
|
||||
}
|
||||
|
||||
actualCommitID, _, err := NewCommand("rev-parse", "--verify").AddDynamicArguments(commitID).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
actualCommitID, _, err := gitcmd.NewCommand("rev-parse", "--verify").AddDynamicArguments(commitID).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
actualCommitID = strings.TrimSpace(actualCommitID)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "unknown revision or path") ||
|
||||
|
||||
@ -11,12 +11,13 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
// ResolveReference resolves a name to a reference
|
||||
func (repo *Repository) ResolveReference(name string) (string, error) {
|
||||
stdout, _, err := NewCommand("show-ref", "--hash").AddDynamicArguments(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := gitcmd.NewCommand("show-ref", "--hash").AddDynamicArguments(name).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "not a valid ref") {
|
||||
return "", ErrNotExist{name, ""}
|
||||
@ -52,13 +53,13 @@ func (repo *Repository) GetRefCommitID(name string) (string, error) {
|
||||
|
||||
// SetReference sets the commit ID string of given reference (e.g. branch or tag).
|
||||
func (repo *Repository) SetReference(name, commitID string) error {
|
||||
_, _, err := NewCommand("update-ref").AddDynamicArguments(name, commitID).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
_, _, err := gitcmd.NewCommand("update-ref").AddDynamicArguments(name, commitID).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
return err
|
||||
}
|
||||
|
||||
// RemoveReference removes the given reference (e.g. branch or tag).
|
||||
func (repo *Repository) RemoveReference(name string) error {
|
||||
_, _, err := NewCommand("update-ref", "--no-deref", "-d").AddDynamicArguments(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
_, _, err := gitcmd.NewCommand("update-ref", "--no-deref", "-d").AddDynamicArguments(name).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -68,7 +69,7 @@ func (repo *Repository) IsCommitExist(name string) bool {
|
||||
log.Error("IsCommitExist: %v", err)
|
||||
return false
|
||||
}
|
||||
_, _, err := NewCommand("cat-file", "-e").AddDynamicArguments(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
_, _, err := gitcmd.NewCommand("cat-file", "-e").AddDynamicArguments(name).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
return err == nil
|
||||
}
|
||||
|
||||
|
||||
@ -6,13 +6,15 @@ package git
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// WriteCommitGraph write commit graph to speed up repo access
|
||||
// this requires git v2.18 to be installed
|
||||
func WriteCommitGraph(ctx context.Context, repoPath string) error {
|
||||
if DefaultFeatures().CheckVersionAtLeast("2.18") {
|
||||
if _, _, err := NewCommand("commit-graph", "write").RunStdString(ctx, &RunOpts{Dir: repoPath}); err != nil {
|
||||
if _, _, err := gitcmd.NewCommand("commit-graph", "write").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}); err != nil {
|
||||
return fmt.Errorf("unable to write commit-graph for '%s' : %w", repoPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,6 +16,8 @@ import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// GetMergeBase checks and returns merge base of two branches and the reference used as base.
|
||||
@ -27,13 +29,13 @@ func (repo *Repository) GetMergeBase(tmpRemote, base, head string) (string, stri
|
||||
if tmpRemote != "origin" {
|
||||
tmpBaseName := RemotePrefix + tmpRemote + "/tmp_" + base
|
||||
// Fetch commit into a temporary branch in order to be able to handle commits and tags
|
||||
_, _, err := NewCommand("fetch", "--no-tags").AddDynamicArguments(tmpRemote).AddDashesAndList(base+":"+tmpBaseName).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
_, _, err := gitcmd.NewCommand("fetch", "--no-tags").AddDynamicArguments(tmpRemote).AddDashesAndList(base+":"+tmpBaseName).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err == nil {
|
||||
base = tmpBaseName
|
||||
}
|
||||
}
|
||||
|
||||
stdout, _, err := NewCommand("merge-base").AddDashesAndList(base, head).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := gitcmd.NewCommand("merge-base").AddDashesAndList(base, head).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
return strings.TrimSpace(stdout), base, err
|
||||
}
|
||||
|
||||
@ -61,8 +63,8 @@ func (repo *Repository) GetDiffNumChangedFiles(base, head string, directComparis
|
||||
}
|
||||
|
||||
// avoid: ambiguous argument 'refs/a...refs/b': unknown revision or path not in the working tree. Use '--': 'git <command> [<revision>...] -- [<file>...]'
|
||||
if err := NewCommand("diff", "-z", "--name-only").AddDynamicArguments(base+separator+head).AddArguments("--").
|
||||
Run(repo.Ctx, &RunOpts{
|
||||
if err := gitcmd.NewCommand("diff", "-z", "--name-only").AddDynamicArguments(base+separator+head).AddArguments("--").
|
||||
Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: w,
|
||||
Stderr: stderr,
|
||||
@ -72,7 +74,7 @@ func (repo *Repository) GetDiffNumChangedFiles(base, head string, directComparis
|
||||
// previously it would return the results of git diff -z --name-only base head so let's try that...
|
||||
w = &lineCountWriter{}
|
||||
stderr.Reset()
|
||||
if err = NewCommand("diff", "-z", "--name-only").AddDynamicArguments(base, head).AddArguments("--").Run(repo.Ctx, &RunOpts{
|
||||
if err = gitcmd.NewCommand("diff", "-z", "--name-only").AddDynamicArguments(base, head).AddArguments("--").Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: w,
|
||||
Stderr: stderr,
|
||||
@ -87,13 +89,13 @@ func (repo *Repository) GetDiffNumChangedFiles(base, head string, directComparis
|
||||
|
||||
// GetDiffShortStatByCmdArgs counts number of changed files, number of additions and deletions
|
||||
// TODO: it can be merged with another "GetDiffShortStat" in the future
|
||||
func GetDiffShortStatByCmdArgs(ctx context.Context, repoPath string, trustedArgs TrustedCmdArgs, dynamicArgs ...string) (numFiles, totalAdditions, totalDeletions int, err error) {
|
||||
func GetDiffShortStatByCmdArgs(ctx context.Context, repoPath string, trustedArgs gitcmd.TrustedCmdArgs, dynamicArgs ...string) (numFiles, totalAdditions, totalDeletions int, err error) {
|
||||
// Now if we call:
|
||||
// $ git diff --shortstat 1ebb35b98889ff77299f24d82da426b434b0cca0...788b8b1440462d477f45b0088875
|
||||
// we get:
|
||||
// " 9902 files changed, 2034198 insertions(+), 298800 deletions(-)\n"
|
||||
cmd := NewCommand("diff", "--shortstat").AddArguments(trustedArgs...).AddDynamicArguments(dynamicArgs...)
|
||||
stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
cmd := gitcmd.NewCommand("diff", "--shortstat").AddArguments(trustedArgs...).AddDynamicArguments(dynamicArgs...)
|
||||
stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
@ -139,8 +141,8 @@ func parseDiffStat(stdout string) (numFiles, totalAdditions, totalDeletions int,
|
||||
// GetDiff generates and returns patch data between given revisions, optimized for human readability
|
||||
func (repo *Repository) GetDiff(compareArg string, w io.Writer) error {
|
||||
stderr := new(bytes.Buffer)
|
||||
return NewCommand("diff", "-p").AddDynamicArguments(compareArg).
|
||||
Run(repo.Ctx, &RunOpts{
|
||||
return gitcmd.NewCommand("diff", "-p").AddDynamicArguments(compareArg).
|
||||
Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: w,
|
||||
Stderr: stderr,
|
||||
@ -149,7 +151,7 @@ func (repo *Repository) GetDiff(compareArg string, w io.Writer) error {
|
||||
|
||||
// GetDiffBinary generates and returns patch data between given revisions, including binary diffs.
|
||||
func (repo *Repository) GetDiffBinary(compareArg string, w io.Writer) error {
|
||||
return NewCommand("diff", "-p", "--binary", "--histogram").AddDynamicArguments(compareArg).Run(repo.Ctx, &RunOpts{
|
||||
return gitcmd.NewCommand("diff", "-p", "--binary", "--histogram").AddDynamicArguments(compareArg).Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: w,
|
||||
})
|
||||
@ -158,8 +160,8 @@ func (repo *Repository) GetDiffBinary(compareArg string, w io.Writer) error {
|
||||
// GetPatch generates and returns format-patch data between given revisions, able to be used with `git apply`
|
||||
func (repo *Repository) GetPatch(compareArg string, w io.Writer) error {
|
||||
stderr := new(bytes.Buffer)
|
||||
return NewCommand("format-patch", "--binary", "--stdout").AddDynamicArguments(compareArg).
|
||||
Run(repo.Ctx, &RunOpts{
|
||||
return gitcmd.NewCommand("format-patch", "--binary", "--stdout").AddDynamicArguments(compareArg).
|
||||
Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: w,
|
||||
Stderr: stderr,
|
||||
@ -174,13 +176,13 @@ func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cmd := NewCommand("diff-tree", "--name-only", "--root", "--no-commit-id", "-r", "-z")
|
||||
cmd := gitcmd.NewCommand("diff-tree", "--name-only", "--root", "--no-commit-id", "-r", "-z")
|
||||
if base == objectFormat.EmptyObjectID().String() {
|
||||
cmd.AddDynamicArguments(head)
|
||||
} else {
|
||||
cmd.AddDynamicArguments(base, head)
|
||||
}
|
||||
stdout, _, err := cmd.RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := cmd.RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/process"
|
||||
)
|
||||
|
||||
@ -42,7 +43,7 @@ func (repo *Repository) GetDefaultPublicGPGKey(forceUpdate bool) (*GPGSettings,
|
||||
Sign: true,
|
||||
}
|
||||
|
||||
value, _, _ := NewCommand("config", "--get", "commit.gpgsign").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
value, _, _ := gitcmd.NewCommand("config", "--get", "commit.gpgsign").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
sign, valid := ParseBool(strings.TrimSpace(value))
|
||||
if !sign || !valid {
|
||||
gpgSettings.Sign = false
|
||||
@ -50,16 +51,16 @@ func (repo *Repository) GetDefaultPublicGPGKey(forceUpdate bool) (*GPGSettings,
|
||||
return gpgSettings, nil
|
||||
}
|
||||
|
||||
signingKey, _, _ := NewCommand("config", "--get", "user.signingkey").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
signingKey, _, _ := gitcmd.NewCommand("config", "--get", "user.signingkey").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
gpgSettings.KeyID = strings.TrimSpace(signingKey)
|
||||
|
||||
format, _, _ := NewCommand("config", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
format, _, _ := gitcmd.NewCommand("config", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
gpgSettings.Format = strings.TrimSpace(format)
|
||||
|
||||
defaultEmail, _, _ := NewCommand("config", "--get", "user.email").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
defaultEmail, _, _ := gitcmd.NewCommand("config", "--get", "user.email").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
gpgSettings.Email = strings.TrimSpace(defaultEmail)
|
||||
|
||||
defaultName, _, _ := NewCommand("config", "--get", "user.name").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
defaultName, _, _ := gitcmd.NewCommand("config", "--get", "user.name").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
gpgSettings.Name = strings.TrimSpace(defaultName)
|
||||
|
||||
if err := gpgSettings.LoadPublicKeyContent(); err != nil {
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
@ -21,7 +22,7 @@ func (repo *Repository) ReadTreeToIndex(treeish string, indexFilename ...string)
|
||||
}
|
||||
|
||||
if len(treeish) != objectFormat.FullLength() {
|
||||
res, _, err := NewCommand("rev-parse", "--verify").AddDynamicArguments(treeish).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
res, _, err := gitcmd.NewCommand("rev-parse", "--verify").AddDynamicArguments(treeish).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -41,7 +42,7 @@ func (repo *Repository) readTreeToIndex(id ObjectID, indexFilename ...string) er
|
||||
if len(indexFilename) > 0 {
|
||||
env = append(os.Environ(), "GIT_INDEX_FILE="+indexFilename[0])
|
||||
}
|
||||
_, _, err := NewCommand("read-tree").AddDynamicArguments(id.String()).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path, Env: env})
|
||||
_, _, err := gitcmd.NewCommand("read-tree").AddDynamicArguments(id.String()).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path, Env: env})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -74,14 +75,14 @@ func (repo *Repository) ReadTreeToTemporaryIndex(treeish string) (tmpIndexFilena
|
||||
|
||||
// EmptyIndex empties the index
|
||||
func (repo *Repository) EmptyIndex() error {
|
||||
_, _, err := NewCommand("read-tree", "--empty").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
_, _, err := gitcmd.NewCommand("read-tree", "--empty").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
return err
|
||||
}
|
||||
|
||||
// LsFiles checks if the given filenames are in the index
|
||||
func (repo *Repository) LsFiles(filenames ...string) ([]string, error) {
|
||||
cmd := NewCommand("ls-files", "-z").AddDashesAndList(filenames...)
|
||||
res, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
cmd := gitcmd.NewCommand("ls-files", "-z").AddDashesAndList(filenames...)
|
||||
res, _, err := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -99,7 +100,7 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd := NewCommand("update-index", "--remove", "-z", "--index-info")
|
||||
cmd := gitcmd.NewCommand("update-index", "--remove", "-z", "--index-info")
|
||||
stdout := new(bytes.Buffer)
|
||||
stderr := new(bytes.Buffer)
|
||||
buffer := new(bytes.Buffer)
|
||||
@ -109,7 +110,7 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error {
|
||||
buffer.WriteString("0 blob " + objectFormat.EmptyObjectID().String() + "\t" + file + "\000")
|
||||
}
|
||||
}
|
||||
return cmd.Run(repo.Ctx, &RunOpts{
|
||||
return cmd.Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdin: bytes.NewReader(buffer.Bytes()),
|
||||
Stdout: stdout,
|
||||
@ -125,7 +126,7 @@ type IndexObjectInfo struct {
|
||||
|
||||
// AddObjectsToIndex adds the provided object hashes to the index at the provided filenames
|
||||
func (repo *Repository) AddObjectsToIndex(objects ...IndexObjectInfo) error {
|
||||
cmd := NewCommand("update-index", "--add", "--replace", "-z", "--index-info")
|
||||
cmd := gitcmd.NewCommand("update-index", "--add", "--replace", "-z", "--index-info")
|
||||
stdout := new(bytes.Buffer)
|
||||
stderr := new(bytes.Buffer)
|
||||
buffer := new(bytes.Buffer)
|
||||
@ -133,7 +134,7 @@ func (repo *Repository) AddObjectsToIndex(objects ...IndexObjectInfo) error {
|
||||
// using format: mode SP type SP sha1 TAB path
|
||||
buffer.WriteString(object.Mode + " blob " + object.Object.String() + "\t" + object.Filename + "\000")
|
||||
}
|
||||
return cmd.Run(repo.Ctx, &RunOpts{
|
||||
return cmd.Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdin: bytes.NewReader(buffer.Bytes()),
|
||||
Stdout: stdout,
|
||||
@ -148,7 +149,7 @@ func (repo *Repository) AddObjectToIndex(mode string, object ObjectID, filename
|
||||
|
||||
// WriteTree writes the current index as a tree to the object db and returns its hash
|
||||
func (repo *Repository) WriteTree() (*Tree, error) {
|
||||
stdout, _, runErr := NewCommand("write-tree").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, runErr := gitcmd.NewCommand("write-tree").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if runErr != nil {
|
||||
return nil, runErr
|
||||
}
|
||||
|
||||
@ -8,6 +8,8 @@ import (
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// ObjectType git object type
|
||||
@ -66,15 +68,15 @@ func (repo *Repository) HashObject(reader io.Reader) (ObjectID, error) {
|
||||
}
|
||||
|
||||
func (repo *Repository) hashObject(reader io.Reader, save bool) (string, error) {
|
||||
var cmd *Command
|
||||
var cmd *gitcmd.Command
|
||||
if save {
|
||||
cmd = NewCommand("hash-object", "-w", "--stdin")
|
||||
cmd = gitcmd.NewCommand("hash-object", "-w", "--stdin")
|
||||
} else {
|
||||
cmd = NewCommand("hash-object", "--stdin")
|
||||
cmd = gitcmd.NewCommand("hash-object", "--stdin")
|
||||
}
|
||||
stdout := new(bytes.Buffer)
|
||||
stderr := new(bytes.Buffer)
|
||||
err := cmd.Run(repo.Ctx, &RunOpts{
|
||||
err := cmd.Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdin: reader,
|
||||
Stdout: stdout,
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
@ -18,7 +19,7 @@ func (repo *Repository) GetRefs() ([]*Reference, error) {
|
||||
// ListOccurrences lists all refs of the given refType the given commit appears in sorted by creation date DESC
|
||||
// refType should only be a literal "branch" or "tag" and nothing else
|
||||
func (repo *Repository) ListOccurrences(ctx context.Context, refType, commitSHA string) ([]string, error) {
|
||||
cmd := NewCommand()
|
||||
cmd := gitcmd.NewCommand()
|
||||
switch refType {
|
||||
case "branch":
|
||||
cmd.AddArguments("branch")
|
||||
@ -27,7 +28,7 @@ func (repo *Repository) ListOccurrences(ctx context.Context, refType, commitSHA
|
||||
default:
|
||||
return nil, util.NewInvalidArgumentErrorf(`can only use "branch" or "tag" for refType, but got %q`, refType)
|
||||
}
|
||||
stdout, _, err := cmd.AddArguments("--no-color", "--sort=-creatordate", "--contains").AddDynamicArguments(commitSHA).RunStdString(ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := cmd.AddArguments("--no-color", "--sort=-creatordate", "--contains").AddDynamicArguments(commitSHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -9,6 +9,8 @@ import (
|
||||
"bufio"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// GetRefsFiltered returns all references of the repository that matches patterm exactly or starting with.
|
||||
@ -21,13 +23,13 @@ func (repo *Repository) GetRefsFiltered(pattern string) ([]*Reference, error) {
|
||||
|
||||
go func() {
|
||||
stderrBuilder := &strings.Builder{}
|
||||
err := NewCommand("for-each-ref").Run(repo.Ctx, &RunOpts{
|
||||
err := gitcmd.NewCommand("for-each-ref").Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: stdoutWriter,
|
||||
Stderr: stderrBuilder,
|
||||
})
|
||||
if err != nil {
|
||||
_ = stdoutWriter.CloseWithError(ConcatenateError(err, stderrBuilder.String()))
|
||||
_ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, stderrBuilder.String()))
|
||||
} else {
|
||||
_ = stdoutWriter.Close()
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// CodeActivityStats represents git statistics data
|
||||
@ -40,9 +41,9 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string)
|
||||
|
||||
since := fromTime.Format(time.RFC3339)
|
||||
|
||||
stdout, _, runErr := NewCommand("rev-list", "--count", "--no-merges", "--branches=*", "--date=iso").
|
||||
stdout, _, runErr := gitcmd.NewCommand("rev-list", "--count", "--no-merges", "--branches=*", "--date=iso").
|
||||
AddOptionFormat("--since=%s", since).
|
||||
RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if runErr != nil {
|
||||
return nil, runErr
|
||||
}
|
||||
@ -62,7 +63,7 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string)
|
||||
_ = stdoutWriter.Close()
|
||||
}()
|
||||
|
||||
gitCmd := NewCommand("log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%aN%n%aE%n", "--date=iso").
|
||||
gitCmd := gitcmd.NewCommand("log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%aN%n%aE%n", "--date=iso").
|
||||
AddOptionFormat("--since=%s", since)
|
||||
if len(branch) == 0 {
|
||||
gitCmd.AddArguments("--branches=*")
|
||||
@ -71,7 +72,7 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string)
|
||||
}
|
||||
|
||||
stderr := new(strings.Builder)
|
||||
err = gitCmd.Run(repo.Ctx, &RunOpts{
|
||||
err = gitCmd.Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Env: []string{},
|
||||
Dir: repo.Path,
|
||||
Stdout: stdoutWriter,
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/foreachref"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
@ -18,13 +19,13 @@ const TagPrefix = "refs/tags/"
|
||||
|
||||
// CreateTag create one tag in the repository
|
||||
func (repo *Repository) CreateTag(name, revision string) error {
|
||||
_, _, err := NewCommand("tag").AddDashesAndList(name, revision).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
_, _, err := gitcmd.NewCommand("tag").AddDashesAndList(name, revision).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateAnnotatedTag create one annotated tag in the repository
|
||||
func (repo *Repository) CreateAnnotatedTag(name, message, revision string) error {
|
||||
_, _, err := NewCommand("tag", "-a", "-m").AddDynamicArguments(message).AddDashesAndList(name, revision).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
_, _, err := gitcmd.NewCommand("tag", "-a", "-m").AddDynamicArguments(message).AddDashesAndList(name, revision).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -34,7 +35,7 @@ func (repo *Repository) GetTagNameBySHA(sha string) (string, error) {
|
||||
return "", fmt.Errorf("SHA is too short: %s", sha)
|
||||
}
|
||||
|
||||
stdout, _, err := NewCommand("show-ref", "--tags", "-d").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := gitcmd.NewCommand("show-ref", "--tags", "-d").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -57,7 +58,7 @@ func (repo *Repository) GetTagNameBySHA(sha string) (string, error) {
|
||||
|
||||
// GetTagID returns the object ID for a tag (annotated tags have both an object SHA AND a commit SHA)
|
||||
func (repo *Repository) GetTagID(name string) (string, error) {
|
||||
stdout, _, err := NewCommand("show-ref", "--tags").AddDashesAndList(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := gitcmd.NewCommand("show-ref", "--tags").AddDashesAndList(name).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -114,14 +115,14 @@ func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, int, error) {
|
||||
defer stdoutReader.Close()
|
||||
defer stdoutWriter.Close()
|
||||
stderr := strings.Builder{}
|
||||
rc := &RunOpts{Dir: repo.Path, Stdout: stdoutWriter, Stderr: &stderr}
|
||||
rc := &gitcmd.RunOpts{Dir: repo.Path, Stdout: stdoutWriter, Stderr: &stderr}
|
||||
|
||||
go func() {
|
||||
err := NewCommand("for-each-ref").
|
||||
err := gitcmd.NewCommand("for-each-ref").
|
||||
AddOptionFormat("--format=%s", forEachRefFmt.Flag()).
|
||||
AddArguments("--sort", "-*creatordate", "refs/tags").Run(repo.Ctx, rc)
|
||||
if err != nil {
|
||||
_ = stdoutWriter.CloseWithError(ConcatenateError(err, stderr.String()))
|
||||
_ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, stderr.String()))
|
||||
} else {
|
||||
_ = stdoutWriter.Close()
|
||||
}
|
||||
|
||||
@ -9,6 +9,8 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// CommitTreeOpts represents the possible options to CommitTree
|
||||
@ -33,7 +35,7 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt
|
||||
"GIT_COMMITTER_EMAIL="+committer.Email,
|
||||
"GIT_COMMITTER_DATE="+commitTimeStr,
|
||||
)
|
||||
cmd := NewCommand("commit-tree").AddDynamicArguments(tree.ID.String())
|
||||
cmd := gitcmd.NewCommand("commit-tree").AddDynamicArguments(tree.ID.String())
|
||||
|
||||
for _, parent := range opts.Parents {
|
||||
cmd.AddArguments("-p").AddDynamicArguments(parent)
|
||||
@ -58,7 +60,7 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt
|
||||
|
||||
stdout := new(bytes.Buffer)
|
||||
stderr := new(bytes.Buffer)
|
||||
err := cmd.Run(repo.Ctx, &RunOpts{
|
||||
err := cmd.Run(repo.Ctx, &gitcmd.RunOpts{
|
||||
Env: env,
|
||||
Dir: repo.Path,
|
||||
Stdin: messageBytes,
|
||||
@ -66,7 +68,7 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt
|
||||
Stderr: stderr,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, ConcatenateError(err, stderr.String())
|
||||
return nil, gitcmd.ConcatenateError(err, stderr.String())
|
||||
}
|
||||
return NewIDFromString(strings.TrimSpace(stdout.String()))
|
||||
}
|
||||
|
||||
@ -9,6 +9,8 @@ package git
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
)
|
||||
|
||||
@ -36,7 +38,7 @@ func (repo *Repository) GetTree(idStr string) (*Tree, error) {
|
||||
}
|
||||
|
||||
if len(idStr) != objectFormat.FullLength() {
|
||||
res, _, err := NewCommand("rev-parse", "--verify").AddDynamicArguments(idStr).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
res, _, err := gitcmd.NewCommand("rev-parse", "--verify").AddDynamicArguments(idStr).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
@ -24,7 +25,7 @@ func GetTemplateSubmoduleCommits(ctx context.Context, repoPath string) (submodul
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts := &RunOpts{
|
||||
opts := &gitcmd.RunOpts{
|
||||
Dir: repoPath,
|
||||
Stdout: stdoutWriter,
|
||||
PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error {
|
||||
@ -45,7 +46,7 @@ func GetTemplateSubmoduleCommits(ctx context.Context, repoPath string) (submodul
|
||||
return scanner.Err()
|
||||
},
|
||||
}
|
||||
err = NewCommand("ls-tree", "-r", "--", "HEAD").Run(ctx, opts)
|
||||
err = gitcmd.NewCommand("ls-tree", "-r", "--", "HEAD").Run(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetTemplateSubmoduleCommits: error running git ls-tree: %v", err)
|
||||
}
|
||||
@ -56,8 +57,8 @@ func GetTemplateSubmoduleCommits(ctx context.Context, repoPath string) (submodul
|
||||
// It is only for generating new repos based on existing template, requires the .gitmodules file to be already present in the work dir.
|
||||
func AddTemplateSubmoduleIndexes(ctx context.Context, repoPath string, submodules []TemplateSubmoduleCommit) error {
|
||||
for _, submodule := range submodules {
|
||||
cmd := NewCommand("update-index", "--add", "--cacheinfo", "160000").AddDynamicArguments(submodule.Commit, submodule.Path)
|
||||
if stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}); err != nil {
|
||||
cmd := gitcmd.NewCommand("update-index", "--add", "--cacheinfo", "160000").AddDynamicArguments(submodule.Commit, submodule.Path)
|
||||
if stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}); err != nil {
|
||||
log.Error("Unable to add %s as submodule to repo %s: stdout %s\nError: %v", submodule.Path, repoPath, stdout, err)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -8,6 +8,8 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@ -30,14 +32,14 @@ func TestAddTemplateSubmoduleIndexes(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
tmpDir := t.TempDir()
|
||||
var err error
|
||||
_, _, err = NewCommand("init").RunStdString(ctx, &RunOpts{Dir: tmpDir})
|
||||
_, _, err = gitcmd.NewCommand("init").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpDir})
|
||||
require.NoError(t, err)
|
||||
_ = os.Mkdir(filepath.Join(tmpDir, "new-dir"), 0o755)
|
||||
err = AddTemplateSubmoduleIndexes(ctx, tmpDir, []TemplateSubmoduleCommit{{Path: "new-dir", Commit: "1234567890123456789012345678901234567890"}})
|
||||
require.NoError(t, err)
|
||||
_, _, err = NewCommand("add", "--all").RunStdString(ctx, &RunOpts{Dir: tmpDir})
|
||||
_, _, err = gitcmd.NewCommand("add", "--all").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpDir})
|
||||
require.NoError(t, err)
|
||||
_, _, err = NewCommand("-c", "user.name=a", "-c", "user.email=b", "commit", "-m=test").RunStdString(ctx, &RunOpts{Dir: tmpDir})
|
||||
_, _, err = gitcmd.NewCommand("-c", "user.name=a", "-c", "user.email=b", "commit", "-m=test").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpDir})
|
||||
require.NoError(t, err)
|
||||
submodules, err := GetTemplateSubmoduleCommits(t.Context(), tmpDir)
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -7,6 +7,8 @@ package git
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// NewTree create a new tree according the repository and tree id
|
||||
@ -48,10 +50,10 @@ func (t *Tree) SubTree(rpath string) (*Tree, error) {
|
||||
|
||||
// LsTree checks if the given filenames are in the tree
|
||||
func (repo *Repository) LsTree(ref string, filenames ...string) ([]string, error) {
|
||||
cmd := NewCommand("ls-tree", "-z", "--name-only").
|
||||
cmd := gitcmd.NewCommand("ls-tree", "-z", "--name-only").
|
||||
AddDashesAndList(append([]string{ref}, filenames...)...)
|
||||
|
||||
res, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
res, _, err := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -65,9 +67,9 @@ func (repo *Repository) LsTree(ref string, filenames ...string) ([]string, error
|
||||
|
||||
// GetTreePathLatestCommit returns the latest commit of a tree path
|
||||
func (repo *Repository) GetTreePathLatestCommit(refName, treePath string) (*Commit, error) {
|
||||
stdout, _, err := NewCommand("rev-list", "-1").
|
||||
stdout, _, err := gitcmd.NewCommand("rev-list", "-1").
|
||||
AddDynamicArguments(refName).AddDashesAndList(treePath).
|
||||
RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -8,6 +8,8 @@ package git
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// Tree represents a flat directory listing.
|
||||
@ -70,7 +72,7 @@ func (t *Tree) ListEntries() (Entries, error) {
|
||||
}
|
||||
}
|
||||
|
||||
stdout, _, runErr := NewCommand("ls-tree", "-l").AddDynamicArguments(t.ID.String()).RunStdBytes(t.repo.Ctx, &RunOpts{Dir: t.repo.Path})
|
||||
stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-l").AddDynamicArguments(t.ID.String()).RunStdBytes(t.repo.Ctx, &gitcmd.RunOpts{Dir: t.repo.Path})
|
||||
if runErr != nil {
|
||||
if strings.Contains(runErr.Error(), "fatal: Not a valid object name") || strings.Contains(runErr.Error(), "fatal: not a tree object") {
|
||||
return nil, ErrNotExist{
|
||||
@ -91,15 +93,15 @@ func (t *Tree) ListEntries() (Entries, error) {
|
||||
|
||||
// listEntriesRecursive returns all entries of current tree recursively including all subtrees
|
||||
// extraArgs could be "-l" to get the size, which is slower
|
||||
func (t *Tree) listEntriesRecursive(extraArgs TrustedCmdArgs) (Entries, error) {
|
||||
func (t *Tree) listEntriesRecursive(extraArgs gitcmd.TrustedCmdArgs) (Entries, error) {
|
||||
if t.entriesRecursiveParsed {
|
||||
return t.entriesRecursive, nil
|
||||
}
|
||||
|
||||
stdout, _, runErr := NewCommand("ls-tree", "-t", "-r").
|
||||
stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-t", "-r").
|
||||
AddArguments(extraArgs...).
|
||||
AddDynamicArguments(t.ID.String()).
|
||||
RunStdBytes(t.repo.Ctx, &RunOpts{Dir: t.repo.Path})
|
||||
RunStdBytes(t.repo.Ctx, &gitcmd.RunOpts{Dir: t.repo.Path})
|
||||
if runErr != nil {
|
||||
return nil, runErr
|
||||
}
|
||||
@ -120,5 +122,5 @@ func (t *Tree) ListEntriesRecursiveFast() (Entries, error) {
|
||||
|
||||
// ListEntriesRecursiveWithSize returns all entries of current tree recursively including all subtrees, with size
|
||||
func (t *Tree) ListEntriesRecursiveWithSize() (Entries, error) {
|
||||
return t.listEntriesRecursive(TrustedCmdArgs{"--long"})
|
||||
return t.listEntriesRecursive(gitcmd.TrustedCmdArgs{"--long"})
|
||||
}
|
||||
|
||||
@ -6,7 +6,6 @@ package git
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -42,14 +41,6 @@ func (oc *ObjectCache[T]) Get(id string) (T, bool) {
|
||||
return obj, has
|
||||
}
|
||||
|
||||
// ConcatenateError concatenats an error with stderr string
|
||||
func ConcatenateError(err error, stderr string) error {
|
||||
if len(stderr) == 0 {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("%w - %s", err, stderr)
|
||||
}
|
||||
|
||||
// ParseBool returns the boolean value represented by the string as per git's git_config_bool
|
||||
// true will be returned for the result if the string is empty, but valid will be false.
|
||||
// "true", "yes", "on" are all true, true
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// GetBranchesByPath returns a branch by its path
|
||||
@ -33,9 +34,9 @@ func GetBranchCommitID(ctx context.Context, repo Repository, branch string) (str
|
||||
|
||||
// SetDefaultBranch sets default branch of repository.
|
||||
func SetDefaultBranch(ctx context.Context, repo Repository, name string) error {
|
||||
_, _, err := git.NewCommand("symbolic-ref", "HEAD").
|
||||
_, _, err := gitcmd.NewCommand("symbolic-ref", "HEAD").
|
||||
AddDynamicArguments(git.BranchPrefix+name).
|
||||
RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)})
|
||||
RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@ -7,14 +7,14 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/globallock"
|
||||
)
|
||||
|
||||
func GitConfigGet(ctx context.Context, repo Repository, key string) (string, error) {
|
||||
result, _, err := git.NewCommand("config", "--get").
|
||||
result, _, err := gitcmd.NewCommand("config", "--get").
|
||||
AddDynamicArguments(key).
|
||||
RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)})
|
||||
RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -28,9 +28,9 @@ func getRepoConfigLockKey(repoStoragePath string) string {
|
||||
// GitConfigAdd add a git configuration key to a specific value for the given repository.
|
||||
func GitConfigAdd(ctx context.Context, repo Repository, key, value string) error {
|
||||
return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error {
|
||||
_, _, err := git.NewCommand("config", "--add").
|
||||
_, _, err := gitcmd.NewCommand("config", "--add").
|
||||
AddDynamicArguments(key, value).
|
||||
RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)})
|
||||
RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
|
||||
return err
|
||||
})
|
||||
}
|
||||
@ -40,9 +40,9 @@ func GitConfigAdd(ctx context.Context, repo Repository, key, value string) error
|
||||
// If the key exists, it will be updated to the new value.
|
||||
func GitConfigSet(ctx context.Context, repo Repository, key, value string) error {
|
||||
return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error {
|
||||
_, _, err := git.NewCommand("config").
|
||||
_, _, err := gitcmd.NewCommand("config").
|
||||
AddDynamicArguments(key, value).
|
||||
RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)})
|
||||
RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
@ -7,10 +7,10 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// Fsck verifies the connectivity and validity of the objects in the database
|
||||
func Fsck(ctx context.Context, repo Repository, timeout time.Duration, args git.TrustedCmdArgs) error {
|
||||
return git.NewCommand("fsck").AddArguments(args...).Run(ctx, &git.RunOpts{Timeout: timeout, Dir: repoPath(repo)})
|
||||
func Fsck(ctx context.Context, repo Repository, timeout time.Duration, args gitcmd.TrustedCmdArgs) error {
|
||||
return gitcmd.NewCommand("fsck").AddArguments(args...).Run(ctx, &gitcmd.RunOpts{Timeout: timeout, Dir: repoPath(repo)})
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
giturl "code.gitea.io/gitea/modules/git/url"
|
||||
"code.gitea.io/gitea/modules/globallock"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
@ -24,7 +25,7 @@ const (
|
||||
|
||||
func GitRemoteAdd(ctx context.Context, repo Repository, remoteName, remoteURL string, options ...RemoteOption) error {
|
||||
return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error {
|
||||
cmd := git.NewCommand("remote", "add")
|
||||
cmd := gitcmd.NewCommand("remote", "add")
|
||||
if len(options) > 0 {
|
||||
switch options[0] {
|
||||
case RemoteOptionMirrorPush:
|
||||
@ -37,15 +38,15 @@ func GitRemoteAdd(ctx context.Context, repo Repository, remoteName, remoteURL st
|
||||
}
|
||||
_, _, err := cmd.
|
||||
AddDynamicArguments(remoteName, remoteURL).
|
||||
RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)})
|
||||
RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func GitRemoteRemove(ctx context.Context, repo Repository, remoteName string) error {
|
||||
return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error {
|
||||
cmd := git.NewCommand("remote", "rm").AddDynamicArguments(remoteName)
|
||||
_, _, err := cmd.RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)})
|
||||
cmd := gitcmd.NewCommand("remote", "rm").AddDynamicArguments(remoteName)
|
||||
_, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
|
||||
return err
|
||||
})
|
||||
}
|
||||
@ -64,8 +65,8 @@ func GitRemoteGetURL(ctx context.Context, repo Repository, remoteName string) (*
|
||||
|
||||
// GitRemotePrune prunes the remote branches that no longer exist in the remote repository.
|
||||
func GitRemotePrune(ctx context.Context, repo Repository, remoteName string, timeout time.Duration, stdout, stderr io.Writer) error {
|
||||
return git.NewCommand("remote", "prune").AddDynamicArguments(remoteName).
|
||||
Run(ctx, &git.RunOpts{
|
||||
return gitcmd.NewCommand("remote", "prune").AddDynamicArguments(remoteName).
|
||||
Run(ctx, &gitcmd.RunOpts{
|
||||
Timeout: timeout,
|
||||
Dir: repoPath(repo),
|
||||
Stdout: stdout,
|
||||
@ -75,8 +76,8 @@ func GitRemotePrune(ctx context.Context, repo Repository, remoteName string, tim
|
||||
|
||||
// GitRemoteUpdatePrune updates the remote branches and prunes the ones that no longer exist in the remote repository.
|
||||
func GitRemoteUpdatePrune(ctx context.Context, repo Repository, remoteName string, timeout time.Duration, stdout, stderr io.Writer) error {
|
||||
return git.NewCommand("remote", "update", "--prune").AddDynamicArguments(remoteName).
|
||||
Run(ctx, &git.RunOpts{
|
||||
return gitcmd.NewCommand("remote", "update", "--prune").AddDynamicArguments(remoteName).
|
||||
Run(ctx, &gitcmd.RunOpts{
|
||||
Timeout: timeout,
|
||||
Dir: repoPath(repo),
|
||||
Stdout: stdout,
|
||||
|
||||
184
modules/glob/glob.go
Normal file
184
modules/glob/glob.go
Normal file
@ -0,0 +1,184 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package glob
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// Reference: https://github.com/gobwas/glob/blob/master/glob.go
|
||||
|
||||
type Glob interface {
|
||||
Match(string) bool
|
||||
}
|
||||
|
||||
type globCompiler struct {
|
||||
nonSeparatorChars string
|
||||
globPattern []rune
|
||||
regexpPattern string
|
||||
regexp *regexp.Regexp
|
||||
pos int
|
||||
}
|
||||
|
||||
// compileChars compiles character class patterns like [abc] or [!abc]
|
||||
func (g *globCompiler) compileChars() (string, error) {
|
||||
result := ""
|
||||
if g.pos < len(g.globPattern) && g.globPattern[g.pos] == '!' {
|
||||
g.pos++
|
||||
result += "^"
|
||||
}
|
||||
|
||||
for g.pos < len(g.globPattern) {
|
||||
c := g.globPattern[g.pos]
|
||||
g.pos++
|
||||
|
||||
if c == ']' {
|
||||
return "[" + result + "]", nil
|
||||
}
|
||||
|
||||
if c == '\\' {
|
||||
if g.pos >= len(g.globPattern) {
|
||||
return "", errors.New("unterminated character class escape")
|
||||
}
|
||||
result += "\\" + string(g.globPattern[g.pos])
|
||||
g.pos++
|
||||
} else {
|
||||
result += string(c)
|
||||
}
|
||||
}
|
||||
|
||||
return "", errors.New("unterminated character class")
|
||||
}
|
||||
|
||||
// compile compiles the glob pattern into a regular expression
|
||||
func (g *globCompiler) compile(subPattern bool) (string, error) {
|
||||
result := ""
|
||||
|
||||
for g.pos < len(g.globPattern) {
|
||||
c := g.globPattern[g.pos]
|
||||
g.pos++
|
||||
|
||||
if subPattern && c == '}' {
|
||||
return "(" + result + ")", nil
|
||||
}
|
||||
|
||||
switch c {
|
||||
case '*':
|
||||
if g.pos < len(g.globPattern) && g.globPattern[g.pos] == '*' {
|
||||
g.pos++
|
||||
result += ".*" // match any sequence of characters
|
||||
} else {
|
||||
result += g.nonSeparatorChars + "*" // match any sequence of non-separator characters
|
||||
}
|
||||
case '?':
|
||||
result += g.nonSeparatorChars // match any single non-separator character
|
||||
case '[':
|
||||
chars, err := g.compileChars()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
result += chars
|
||||
case '{':
|
||||
subResult, err := g.compile(true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
result += subResult
|
||||
case ',':
|
||||
if subPattern {
|
||||
result += "|"
|
||||
} else {
|
||||
result += ","
|
||||
}
|
||||
case '\\':
|
||||
if g.pos >= len(g.globPattern) {
|
||||
return "", errors.New("no character to escape")
|
||||
}
|
||||
result += "\\" + string(g.globPattern[g.pos])
|
||||
g.pos++
|
||||
case '.', '+', '^', '$', '(', ')', '|':
|
||||
result += "\\" + string(c) // escape regexp special characters
|
||||
default:
|
||||
result += string(c)
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func newGlobCompiler(pattern string, separators ...rune) (Glob, error) {
|
||||
g := &globCompiler{globPattern: []rune(pattern)}
|
||||
|
||||
// Escape separators for use in character class
|
||||
escapedSeparators := regexp.QuoteMeta(string(separators))
|
||||
if escapedSeparators != "" {
|
||||
g.nonSeparatorChars = "[^" + escapedSeparators + "]"
|
||||
} else {
|
||||
g.nonSeparatorChars = "."
|
||||
}
|
||||
|
||||
compiled, err := g.compile(false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g.regexpPattern = "^" + compiled + "$"
|
||||
|
||||
regex, err := regexp.Compile(g.regexpPattern)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to compile regexp: %w", err)
|
||||
}
|
||||
|
||||
g.regexp = regex
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func (g *globCompiler) Match(s string) bool {
|
||||
return g.regexp.MatchString(s)
|
||||
}
|
||||
|
||||
func Compile(pattern string, separators ...rune) (Glob, error) {
|
||||
return newGlobCompiler(pattern, separators...)
|
||||
}
|
||||
|
||||
func MustCompile(pattern string, separators ...rune) Glob {
|
||||
g, err := Compile(pattern, separators...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return g
|
||||
}
|
||||
|
||||
func IsSpecialByte(c byte) bool {
|
||||
return c == '*' || c == '?' || c == '\\' || c == '[' || c == ']' || c == '{' || c == '}'
|
||||
}
|
||||
|
||||
// QuoteMeta returns a string that quotes all glob pattern meta characters
|
||||
// inside the argument text; For example, QuoteMeta(`{foo*}`) returns `\[foo\*\]`.
|
||||
// Reference: https://github.com/gobwas/glob/blob/master/glob.go
|
||||
func QuoteMeta(s string) string {
|
||||
pos := 0
|
||||
for pos < len(s) && !IsSpecialByte(s[pos]) {
|
||||
pos++
|
||||
}
|
||||
if pos == len(s) {
|
||||
return s
|
||||
}
|
||||
b := make([]byte, pos+2*(len(s)-pos))
|
||||
copy(b, s[0:pos])
|
||||
to := pos
|
||||
for ; pos < len(s); pos++ {
|
||||
if IsSpecialByte(s[pos]) {
|
||||
b[to] = '\\'
|
||||
to++
|
||||
}
|
||||
b[to] = s[pos]
|
||||
to++
|
||||
}
|
||||
return util.UnsafeBytesToString(b[0:to])
|
||||
}
|
||||
208
modules/glob/glob_test.go
Normal file
208
modules/glob/glob_test.go
Normal file
@ -0,0 +1,208 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// Copyright (c) 2016 Sergey Kamardin
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
//nolint:revive // the code is from gobwas/glob
|
||||
package glob
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Reference: https://github.com/gobwas/glob/blob/master/glob_test.go
|
||||
|
||||
const (
|
||||
pattern_all = "[a-z][!a-x]*cat*[h][!b]*eyes*"
|
||||
regexp_all = `^[a-z][^a-x].*cat.*[h][^b].*eyes.*$`
|
||||
fixture_all_match = "my cat has very bright eyes"
|
||||
fixture_all_mismatch = "my dog has very bright eyes"
|
||||
|
||||
pattern_plain = "google.com"
|
||||
regexp_plain = `^google\.com$`
|
||||
fixture_plain_match = "google.com"
|
||||
fixture_plain_mismatch = "gobwas.com"
|
||||
|
||||
pattern_multiple = "https://*.google.*"
|
||||
regexp_multiple = `^https:\/\/.*\.google\..*$`
|
||||
fixture_multiple_match = "https://account.google.com"
|
||||
fixture_multiple_mismatch = "https://google.com"
|
||||
|
||||
pattern_alternatives = "{https://*.google.*,*yandex.*,*yahoo.*,*mail.ru}"
|
||||
regexp_alternatives = `^(https:\/\/.*\.google\..*|.*yandex\..*|.*yahoo\..*|.*mail\.ru)$`
|
||||
fixture_alternatives_match = "http://yahoo.com"
|
||||
fixture_alternatives_mismatch = "http://google.com"
|
||||
|
||||
pattern_alternatives_suffix = "{https://*gobwas.com,http://exclude.gobwas.com}"
|
||||
regexp_alternatives_suffix = `^(https:\/\/.*gobwas\.com|http://exclude.gobwas.com)$`
|
||||
fixture_alternatives_suffix_first_match = "https://safe.gobwas.com"
|
||||
fixture_alternatives_suffix_first_mismatch = "http://safe.gobwas.com"
|
||||
fixture_alternatives_suffix_second = "http://exclude.gobwas.com"
|
||||
|
||||
pattern_prefix = "abc*"
|
||||
regexp_prefix = `^abc.*$`
|
||||
pattern_suffix = "*def"
|
||||
regexp_suffix = `^.*def$`
|
||||
pattern_prefix_suffix = "ab*ef"
|
||||
regexp_prefix_suffix = `^ab.*ef$`
|
||||
fixture_prefix_suffix_match = "abcdef"
|
||||
fixture_prefix_suffix_mismatch = "af"
|
||||
|
||||
pattern_alternatives_combine_lite = "{abc*def,abc?def,abc[zte]def}"
|
||||
regexp_alternatives_combine_lite = `^(abc.*def|abc.def|abc[zte]def)$`
|
||||
fixture_alternatives_combine_lite = "abczdef"
|
||||
|
||||
pattern_alternatives_combine_hard = "{abc*[a-c]def,abc?[d-g]def,abc[zte]?def}"
|
||||
regexp_alternatives_combine_hard = `^(abc.*[a-c]def|abc.[d-g]def|abc[zte].def)$`
|
||||
fixture_alternatives_combine_hard = "abczqdef"
|
||||
)
|
||||
|
||||
type test struct {
|
||||
pattern, match string
|
||||
should bool
|
||||
delimiters []rune
|
||||
}
|
||||
|
||||
func glob(s bool, p, m string, d ...rune) test {
|
||||
return test{p, m, s, d}
|
||||
}
|
||||
|
||||
func TestGlob(t *testing.T) {
|
||||
for _, test := range []test{
|
||||
glob(true, "* ?at * eyes", "my cat has very bright eyes"),
|
||||
|
||||
glob(true, "", ""),
|
||||
glob(false, "", "b"),
|
||||
|
||||
glob(true, "*ä", "åä"),
|
||||
glob(true, "abc", "abc"),
|
||||
glob(true, "a*c", "abc"),
|
||||
glob(true, "a*c", "a12345c"),
|
||||
glob(true, "a?c", "a1c"),
|
||||
glob(true, "a.b", "a.b", '.'),
|
||||
glob(true, "a.*", "a.b", '.'),
|
||||
glob(true, "a.**", "a.b.c", '.'),
|
||||
glob(true, "a.?.c", "a.b.c", '.'),
|
||||
glob(true, "a.?.?", "a.b.c", '.'),
|
||||
glob(true, "?at", "cat"),
|
||||
glob(true, "?at", "fat"),
|
||||
glob(true, "*", "abc"),
|
||||
glob(true, `\*`, "*"),
|
||||
glob(true, "**", "a.b.c", '.'),
|
||||
|
||||
glob(false, "?at", "at"),
|
||||
glob(false, "?at", "fat", 'f'),
|
||||
glob(false, "a.*", "a.b.c", '.'),
|
||||
glob(false, "a.?.c", "a.bb.c", '.'),
|
||||
glob(false, "*", "a.b.c", '.'),
|
||||
|
||||
glob(true, "*test", "this is a test"),
|
||||
glob(true, "this*", "this is a test"),
|
||||
glob(true, "*is *", "this is a test"),
|
||||
glob(true, "*is*a*", "this is a test"),
|
||||
glob(true, "**test**", "this is a test"),
|
||||
glob(true, "**is**a***test*", "this is a test"),
|
||||
|
||||
glob(false, "*is", "this is a test"),
|
||||
glob(false, "*no*", "this is a test"),
|
||||
glob(true, "[!a]*", "this is a test3"),
|
||||
|
||||
glob(true, "*abc", "abcabc"),
|
||||
glob(true, "**abc", "abcabc"),
|
||||
glob(true, "???", "abc"),
|
||||
glob(true, "?*?", "abc"),
|
||||
glob(true, "?*?", "ac"),
|
||||
glob(false, "sta", "stagnation"),
|
||||
glob(true, "sta*", "stagnation"),
|
||||
glob(false, "sta?", "stagnation"),
|
||||
glob(false, "sta?n", "stagnation"),
|
||||
|
||||
glob(true, "{abc,def}ghi", "defghi"),
|
||||
glob(true, "{abc,abcd}a", "abcda"),
|
||||
glob(true, "{a,ab}{bc,f}", "abc"),
|
||||
glob(true, "{*,**}{a,b}", "ab"),
|
||||
glob(false, "{*,**}{a,b}", "ac"),
|
||||
|
||||
glob(true, "/{rate,[a-z][a-z][a-z]}*", "/rate"),
|
||||
glob(true, "/{rate,[0-9][0-9][0-9]}*", "/rate"),
|
||||
glob(true, "/{rate,[a-z][a-z][a-z]}*", "/usd"),
|
||||
|
||||
glob(true, "{*.google.*,*.yandex.*}", "www.google.com", '.'),
|
||||
glob(true, "{*.google.*,*.yandex.*}", "www.yandex.com", '.'),
|
||||
glob(false, "{*.google.*,*.yandex.*}", "yandex.com", '.'),
|
||||
glob(false, "{*.google.*,*.yandex.*}", "google.com", '.'),
|
||||
|
||||
glob(true, "{*.google.*,yandex.*}", "www.google.com", '.'),
|
||||
glob(true, "{*.google.*,yandex.*}", "yandex.com", '.'),
|
||||
glob(false, "{*.google.*,yandex.*}", "www.yandex.com", '.'),
|
||||
glob(false, "{*.google.*,yandex.*}", "google.com", '.'),
|
||||
|
||||
glob(true, "*//{,*.}example.com", "https://www.example.com"),
|
||||
glob(true, "*//{,*.}example.com", "http://example.com"),
|
||||
glob(false, "*//{,*.}example.com", "http://example.com.net"),
|
||||
|
||||
glob(true, pattern_all, fixture_all_match),
|
||||
glob(false, pattern_all, fixture_all_mismatch),
|
||||
|
||||
glob(true, pattern_plain, fixture_plain_match),
|
||||
glob(false, pattern_plain, fixture_plain_mismatch),
|
||||
|
||||
glob(true, pattern_multiple, fixture_multiple_match),
|
||||
glob(false, pattern_multiple, fixture_multiple_mismatch),
|
||||
|
||||
glob(true, pattern_alternatives, fixture_alternatives_match),
|
||||
glob(false, pattern_alternatives, fixture_alternatives_mismatch),
|
||||
|
||||
glob(true, pattern_alternatives_suffix, fixture_alternatives_suffix_first_match),
|
||||
glob(false, pattern_alternatives_suffix, fixture_alternatives_suffix_first_mismatch),
|
||||
glob(true, pattern_alternatives_suffix, fixture_alternatives_suffix_second),
|
||||
|
||||
glob(true, pattern_alternatives_combine_hard, fixture_alternatives_combine_hard),
|
||||
|
||||
glob(true, pattern_alternatives_combine_lite, fixture_alternatives_combine_lite),
|
||||
|
||||
glob(true, pattern_prefix, fixture_prefix_suffix_match),
|
||||
glob(false, pattern_prefix, fixture_prefix_suffix_mismatch),
|
||||
|
||||
glob(true, pattern_suffix, fixture_prefix_suffix_match),
|
||||
glob(false, pattern_suffix, fixture_prefix_suffix_mismatch),
|
||||
|
||||
glob(true, pattern_prefix_suffix, fixture_prefix_suffix_match),
|
||||
glob(false, pattern_prefix_suffix, fixture_prefix_suffix_mismatch),
|
||||
} {
|
||||
g, err := Compile(test.pattern, test.delimiters...)
|
||||
require.NoError(t, err)
|
||||
result := g.Match(test.match)
|
||||
assert.Equal(t, test.should, result, "pattern %q matching %q should be %v but got %v, compiled=%s", test.pattern, test.match, test.should, result, g.(*globCompiler).regexpPattern)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQuoteMeta(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
in, out string
|
||||
}{
|
||||
{
|
||||
in: `[foo*]`,
|
||||
out: `\[foo\*\]`,
|
||||
},
|
||||
{
|
||||
in: `{foo*}`,
|
||||
out: `\{foo\*\}`,
|
||||
},
|
||||
{
|
||||
in: `*?\[]{}`,
|
||||
out: `\*\?\\\[\]\{\}`,
|
||||
},
|
||||
{
|
||||
in: `some text and *?\[]{}`,
|
||||
out: `some text and \*\?\\\[\]\{\}`,
|
||||
},
|
||||
} {
|
||||
act := QuoteMeta(test.in)
|
||||
assert.Equal(t, test.out, act, "QuoteMeta(%q)", test.in)
|
||||
_, err := Compile(act)
|
||||
assert.NoError(t, err, "#%d _, err := Compile(QuoteMeta(%q) = %q); err = %q", id, test.in, act, err)
|
||||
}
|
||||
}
|
||||
@ -16,6 +16,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/analyze"
|
||||
"code.gitea.io/gitea/modules/charset"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/indexer"
|
||||
path_filter "code.gitea.io/gitea/modules/indexer/code/bleve/token/path"
|
||||
"code.gitea.io/gitea/modules/indexer/code/internal"
|
||||
@ -162,7 +163,7 @@ func (b *Indexer) addUpdate(ctx context.Context, batchWriter git.WriteCloserErro
|
||||
var err error
|
||||
if !update.Sized {
|
||||
var stdout string
|
||||
stdout, _, err = git.NewCommand("cat-file", "-s").AddDynamicArguments(update.BlobSha).RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()})
|
||||
stdout, _, err = gitcmd.NewCommand("cat-file", "-s").AddDynamicArguments(update.BlobSha).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/analyze"
|
||||
"code.gitea.io/gitea/modules/charset"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/indexer"
|
||||
"code.gitea.io/gitea/modules/indexer/code/internal"
|
||||
indexer_internal "code.gitea.io/gitea/modules/indexer/internal"
|
||||
@ -147,7 +148,7 @@ func (b *Indexer) addUpdate(ctx context.Context, batchWriter git.WriteCloserErro
|
||||
var err error
|
||||
if !update.Sized {
|
||||
var stdout string
|
||||
stdout, _, err = git.NewCommand("cat-file", "-s").AddDynamicArguments(update.BlobSha).RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()})
|
||||
stdout, _, err = gitcmd.NewCommand("cat-file", "-s").AddDynamicArguments(update.BlobSha).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -250,7 +251,7 @@ func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha st
|
||||
func (b *Indexer) Delete(ctx context.Context, repoID int64) error {
|
||||
if err := b.doDelete(ctx, repoID); err != nil {
|
||||
// Maybe there is a conflict during the delete operation, so we should retry after a refresh
|
||||
log.Warn("Deletion of entries of repo %v within index %v was erroneus. Trying to refresh index before trying again", repoID, b.inner.VersionedIndexName(), err)
|
||||
log.Warn("Deletion of entries of repo %v within index %v was erroneous. Trying to refresh index before trying again", repoID, b.inner.VersionedIndexName(), err)
|
||||
if err := b.refreshIndex(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -10,13 +10,14 @@ import (
|
||||
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/indexer/code/internal"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
func getDefaultBranchSha(ctx context.Context, repo *repo_model.Repository) (string, error) {
|
||||
stdout, _, err := git.NewCommand("show-ref", "-s").AddDynamicArguments(git.BranchPrefix+repo.DefaultBranch).RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()})
|
||||
stdout, _, err := gitcmd.NewCommand("show-ref", "-s").AddDynamicArguments(git.BranchPrefix+repo.DefaultBranch).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -32,8 +33,8 @@ func getRepoChanges(ctx context.Context, repo *repo_model.Repository, revision s
|
||||
|
||||
needGenesis := len(status.CommitSha) == 0
|
||||
if !needGenesis {
|
||||
hasAncestorCmd := git.NewCommand("merge-base").AddDynamicArguments(status.CommitSha, revision)
|
||||
stdout, _, _ := hasAncestorCmd.RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()})
|
||||
hasAncestorCmd := gitcmd.NewCommand("merge-base").AddDynamicArguments(status.CommitSha, revision)
|
||||
stdout, _, _ := hasAncestorCmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()})
|
||||
needGenesis = len(stdout) == 0
|
||||
}
|
||||
|
||||
@ -86,7 +87,7 @@ func parseGitLsTreeOutput(stdout []byte) ([]internal.FileUpdate, error) {
|
||||
// genesisChanges get changes to add repo to the indexer for the first time
|
||||
func genesisChanges(ctx context.Context, repo *repo_model.Repository, revision string) (*internal.RepoChanges, error) {
|
||||
var changes internal.RepoChanges
|
||||
stdout, _, runErr := git.NewCommand("ls-tree", "--full-tree", "-l", "-r").AddDynamicArguments(revision).RunStdBytes(ctx, &git.RunOpts{Dir: repo.RepoPath()})
|
||||
stdout, _, runErr := gitcmd.NewCommand("ls-tree", "--full-tree", "-l", "-r").AddDynamicArguments(revision).RunStdBytes(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()})
|
||||
if runErr != nil {
|
||||
return nil, runErr
|
||||
}
|
||||
@ -98,8 +99,8 @@ func genesisChanges(ctx context.Context, repo *repo_model.Repository, revision s
|
||||
|
||||
// nonGenesisChanges get changes since the previous indexer update
|
||||
func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, revision string) (*internal.RepoChanges, error) {
|
||||
diffCmd := git.NewCommand("diff", "--name-status").AddDynamicArguments(repo.CodeIndexerStatus.CommitSha, revision)
|
||||
stdout, _, runErr := diffCmd.RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()})
|
||||
diffCmd := gitcmd.NewCommand("diff", "--name-status").AddDynamicArguments(repo.CodeIndexerStatus.CommitSha, revision)
|
||||
stdout, _, runErr := diffCmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()})
|
||||
if runErr != nil {
|
||||
// previous commit sha may have been removed by a force push, so
|
||||
// try rebuilding from scratch
|
||||
@ -115,9 +116,9 @@ func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, revisio
|
||||
updatedFilenames := make([]string, 0, 10)
|
||||
|
||||
updateChanges := func() error {
|
||||
cmd := git.NewCommand("ls-tree", "--full-tree", "-l").AddDynamicArguments(revision).
|
||||
cmd := gitcmd.NewCommand("ls-tree", "--full-tree", "-l").AddDynamicArguments(revision).
|
||||
AddDashesAndList(updatedFilenames...)
|
||||
lsTreeStdout, _, err := cmd.RunStdBytes(ctx, &git.RunOpts{Dir: repo.RepoPath()})
|
||||
lsTreeStdout, _, err := cmd.RunStdBytes(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -134,7 +134,7 @@ func testIndexer(name string, t *testing.T, indexer internal.Indexer) {
|
||||
},
|
||||
},
|
||||
// Search for matches on both the contents and the filenames within the repo '62'.
|
||||
// This scenario yields two results: the first result is baed on the file (cucumber.md) while the second is based on the contents
|
||||
// This scenario yields two results: the first result is based on the file (cucumber.md) while the second is based on the contents
|
||||
{
|
||||
RepoIDs: []int64{62},
|
||||
Keyword: "cucumber",
|
||||
|
||||
@ -28,7 +28,7 @@ import (
|
||||
)
|
||||
|
||||
// IndexerMetadata is used to send data to the queue, so it contains only the ids.
|
||||
// It may look weired, because it has to be compatible with the old queue data format.
|
||||
// It may look weird, because it has to be compatible with the old queue data format.
|
||||
// If the IsDelete flag is true, the IDs specify the issues to delete from the index without querying the database.
|
||||
// If the IsDelete flag is false, the ID specify the issue to index, so Indexer will query the database to get the issue data.
|
||||
// It should be noted that if the id is not existing in the database, it's index will be deleted too even if IsDelete is false.
|
||||
|
||||
@ -18,7 +18,7 @@ func resolveLinkRelative(ctx context.Context, base, cur, link string, absolute b
|
||||
}
|
||||
if strings.HasPrefix(link, "/") {
|
||||
if strings.HasPrefix(link, base) && strings.Count(base, "/") >= 4 {
|
||||
// a trick to tolerate that some users were using absolut paths (the old gitea's behavior)
|
||||
// a trick to tolerate that some users were using absolute paths (the old gitea's behavior)
|
||||
finalLink = link
|
||||
} else {
|
||||
finalLink = util.URLJoin(base, "./", link)
|
||||
|
||||
@ -10,10 +10,9 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"code.gitea.io/gitea/modules/glob"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
//
|
||||
// 4. Handler (represented by HandlerFuncT type):
|
||||
// - It's the function responsible for processing items. Each active worker will call it.
|
||||
// - If an item or some items are not psuccessfully rocessed, the handler could return them as "unhandled items".
|
||||
// - If an item or some items are not successfully processed, the handler could return them as "unhandled items".
|
||||
// In such scenarios, the queue system ensures these unhandled items are returned to the base queue after a brief delay.
|
||||
// This mechanism is particularly beneficial in cases where the processing entity (like a document indexer) is
|
||||
// temporarily unavailable. It ensures that no item is skipped or lost due to transient failures in the processing
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
package setting
|
||||
|
||||
import "github.com/gobwas/glob"
|
||||
import "code.gitea.io/gitea/modules/glob"
|
||||
|
||||
type GlobMatcher struct {
|
||||
compiledGlob glob.Glob
|
||||
|
||||
@ -9,10 +9,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/glob"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
)
|
||||
|
||||
// enumerates all the types of captchas
|
||||
|
||||
@ -6,10 +6,10 @@ package setting
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/glob"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ import (
|
||||
type StateType string
|
||||
|
||||
const (
|
||||
// StateOpen pr is opend
|
||||
// StateOpen pr is opened
|
||||
StateOpen StateType = "open"
|
||||
// StateClosed pr is closed
|
||||
StateClosed StateType = "closed"
|
||||
@ -76,6 +76,8 @@ type Issue struct {
|
||||
// swagger:strfmt date-time
|
||||
Deadline *time.Time `json:"due_date"`
|
||||
|
||||
TimeEstimate int64 `json:"time_estimate"`
|
||||
|
||||
PullRequest *PullRequestMeta `json:"pull_request"`
|
||||
Repo *RepositoryMeta `json:"repository"`
|
||||
|
||||
|
||||
@ -319,7 +319,7 @@ const (
|
||||
)
|
||||
|
||||
// Name represents the service type's name
|
||||
// WARNNING: the name have to be equal to that on goth's library
|
||||
// WARNING: the name has to be equal to that on goth's library
|
||||
func (gt GitServiceType) Name() string {
|
||||
return strings.ToLower(gt.Title())
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ type User struct {
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface for User, adding field(s) for backward compatibility
|
||||
func (u User) MarshalJSON() ([]byte, error) {
|
||||
// Re-declaring User to avoid recursion
|
||||
// Redeclaring User to avoid recursion
|
||||
type shadow User
|
||||
return json.Marshal(struct {
|
||||
shadow
|
||||
|
||||
@ -48,12 +48,12 @@ func TestIsSvgImage(t *testing.T) {
|
||||
<!-- Comments -->
|
||||
<svg></svg>`)).IsSvgImage())
|
||||
assert.True(t, DetectContentType([]byte(`<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Multline
|
||||
<!-- Multiline
|
||||
Comment -->
|
||||
<svg></svg>`)).IsSvgImage())
|
||||
assert.True(t, DetectContentType([]byte(`<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Multline
|
||||
<!-- Multiline
|
||||
Comment -->
|
||||
<svg></svg>`)).IsSvgImage())
|
||||
|
||||
|
||||
@ -10,10 +10,10 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/modules/auth"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/glob"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"gitea.com/go-chi/binding"
|
||||
"github.com/gobwas/glob"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@ -6,8 +6,9 @@ package validation
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/glob"
|
||||
|
||||
"gitea.com/go-chi/binding"
|
||||
"github.com/gobwas/glob"
|
||||
)
|
||||
|
||||
func getGlobPatternErrorString(pattern string) string {
|
||||
|
||||
@ -11,9 +11,8 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"code.gitea.io/gitea/modules/glob"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
)
|
||||
|
||||
type globalVarsStruct struct {
|
||||
|
||||
@ -8,7 +8,7 @@ gradle-app.setting
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
|
||||
# Avoid ignore Gradle wrappper properties
|
||||
# Avoid ignore Gradle wrapper properties
|
||||
!gradle-wrapper.properties
|
||||
|
||||
# Cache of project
|
||||
|
||||
@ -3425,7 +3425,6 @@ swift.install=Přidejte balíček do svého <code>Package.swift</code> souboru:
|
||||
swift.install2=a spustit následující příkaz:
|
||||
vagrant.install=Pro přidání Vagrant box spusťte následující příkaz:
|
||||
settings.link=Propojit tento balíček s repozitářem
|
||||
settings.link.description=Pokud propojíte balíček s repozitářem, je tento balíček uveden v seznamu balíčků repozitáře.
|
||||
settings.link.select=Vybrat repozitář
|
||||
settings.link.button=Aktualizovat odkaz na repozitář
|
||||
settings.link.success=Odkaz na repozitář byl úspěšně aktualizován.
|
||||
|
||||
@ -3475,7 +3475,6 @@ swift.install=Füge das Paket deiner <code>Package.swift</code> Datei hinzu:
|
||||
swift.install2=und führe den folgenden Befehl aus:
|
||||
vagrant.install=Um eine Vagrant-Box hinzuzufügen, führe den folgenden Befehl aus:
|
||||
settings.link=Dieses Paket einem Repository zuweisen
|
||||
settings.link.description=Wenn du ein Paket mit einem Repository verknüpfst, wird es in der Paketliste des Repositories angezeigt.
|
||||
settings.link.select=Repository auswählen
|
||||
settings.link.button=Repository-Link aktualisieren
|
||||
settings.link.success=Repository-Link wurde erfolgreich aktualisiert.
|
||||
|
||||
@ -3133,7 +3133,6 @@ swift.install=Προσθέστε το πακέτο στο αρχείο <code>Pac
|
||||
swift.install2=και εκτελέστε την ακόλουθη εντολή:
|
||||
vagrant.install=Για προσθήκη ενός κυτίου Vagrant, εκτελέστε την ακόλουθη εντολή:
|
||||
settings.link=Σύνδεση αυτού του πακέτου με ένα αποθετήριο
|
||||
settings.link.description=Εάν συνδέσετε ένα πακέτο με ένα αποθετήριο, το πακέτο περιλαμβάνεται στη λίστα πακέτων του αποθετηρίου.
|
||||
settings.link.select=Επιλογή Αποθετηρίου
|
||||
settings.link.button=Ενημέρωση Συνδέσμου Αποθετηρίου
|
||||
settings.link.success=Ο σύνδεσμος αποθετηρίου ενημερώθηκε επιτυχώς.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user