mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-10 07:25:09 +02:00
Merge branch 'main' into lunny/refactor_getpatch
This commit is contained in:
commit
50c828361e
@ -79,18 +79,6 @@ cpu.out
|
||||
/public/assets/fonts
|
||||
/public/assets/img/avatar
|
||||
/vendor
|
||||
/web_src/fomantic/node_modules
|
||||
/web_src/fomantic/build/*
|
||||
!/web_src/fomantic/build/semantic.js
|
||||
!/web_src/fomantic/build/semantic.css
|
||||
!/web_src/fomantic/build/themes
|
||||
/web_src/fomantic/build/themes/*
|
||||
!/web_src/fomantic/build/themes/default
|
||||
/web_src/fomantic/build/themes/default/assets/*
|
||||
!/web_src/fomantic/build/themes/default/assets/fonts
|
||||
/web_src/fomantic/build/themes/default/assets/fonts/*
|
||||
!/web_src/fomantic/build/themes/default/assets/fonts/icons.woff2
|
||||
!/web_src/fomantic/build/themes/default/assets/fonts/outline-icons.woff2
|
||||
/VERSION
|
||||
/.air
|
||||
/.go-licenses
|
||||
|
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -5,7 +5,5 @@
|
||||
/public/assets/img/svg/*.svg linguist-generated
|
||||
/templates/swagger/v1_json.tmpl linguist-generated
|
||||
/vendor/** -text -eol linguist-vendored
|
||||
/web_src/fomantic/build/** linguist-generated
|
||||
/web_src/fomantic/_site/globals/site.variables linguist-language=Less
|
||||
/web_src/js/vendor/** -text -eol linguist-vendored
|
||||
Dockerfile.* linguist-language=Dockerfile
|
||||
|
2
.github/workflows/cron-licenses.yml
vendored
2
.github/workflows/cron-licenses.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- run: make generate-license generate-gitignore
|
||||
- run: make generate-gitignore
|
||||
timeout-minutes: 40
|
||||
- name: push translations to repo
|
||||
uses: appleboy/git-push-action@v0.0.3
|
||||
|
2
.github/workflows/pull-compliance.yml
vendored
2
.github/workflows/pull-compliance.yml
vendored
@ -95,7 +95,7 @@ jobs:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- run: make deps-backend deps-tools
|
||||
- run: make lint-go-windows lint-go-vet
|
||||
- run: make lint-go-windows lint-go-gitea-vet
|
||||
env:
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
GOOS: windows
|
||||
|
6
.github/workflows/pull-db-tests.yml
vendored
6
.github/workflows/pull-db-tests.yml
vendored
@ -202,12 +202,10 @@ jobs:
|
||||
test-mssql:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
# specifying the version of ubuntu in use as mssql fails on newer kernels
|
||||
# pending resolution from vendor
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
mssql:
|
||||
image: mcr.microsoft.com/mssql/server:2017-latest
|
||||
image: mcr.microsoft.com/mssql/server:2019-latest
|
||||
env:
|
||||
ACCEPT_EULA: Y
|
||||
MSSQL_PID: Standard
|
||||
|
12
.gitignore
vendored
12
.gitignore
vendored
@ -84,18 +84,6 @@ cpu.out
|
||||
/public/assets/fonts
|
||||
/public/assets/licenses.txt
|
||||
/vendor
|
||||
/web_src/fomantic/node_modules
|
||||
/web_src/fomantic/build/*
|
||||
!/web_src/fomantic/build/semantic.js
|
||||
!/web_src/fomantic/build/semantic.css
|
||||
!/web_src/fomantic/build/themes
|
||||
/web_src/fomantic/build/themes/*
|
||||
!/web_src/fomantic/build/themes/default
|
||||
/web_src/fomantic/build/themes/default/assets/*
|
||||
!/web_src/fomantic/build/themes/default/assets/fonts
|
||||
/web_src/fomantic/build/themes/default/assets/fonts/*
|
||||
!/web_src/fomantic/build/themes/default/assets/fonts/icons.woff2
|
||||
!/web_src/fomantic/build/themes/default/assets/fonts/outline-icons.woff2
|
||||
/VERSION
|
||||
/.air
|
||||
/.go-licenses
|
||||
|
22
CHANGELOG.md
22
CHANGELOG.md
@ -4,6 +4,28 @@ This changelog goes through the changes that have been made in each release
|
||||
without substantial changes to our git log; to see the highlights of what has
|
||||
been added to each release, please refer to the [blog](https://blog.gitea.com).
|
||||
|
||||
## [1.23.5](https://github.com/go-gitea/gitea/releases/tag/v1.23.5) - 2025-03-04
|
||||
|
||||
* SECURITY
|
||||
* Bump x/oauth2 & x/crypto (#33704) (#33727)
|
||||
* PERFORMANCE
|
||||
* Optimize user dashboard loading (#33686) (#33708)
|
||||
* BUGFIXES
|
||||
* Fix navbar dropdown item align (#33782)
|
||||
* Fix inconsistent closed issue list icon (#33722) (#33728)
|
||||
* Fix for Maven Package Naming Convention Handling (#33678) (#33679)
|
||||
* Improve Open-with URL encoding (#33666) (#33680)
|
||||
* Deleting repository should unlink all related packages (#33653) (#33673)
|
||||
* Fix omitempty bug (#33663) (#33670)
|
||||
* Upgrade go-crypto from 1.1.4 to 1.1.6 (#33745) (#33754)
|
||||
* Fix OCI image.version annotation for releases to use full semver (#33698) (#33701)
|
||||
* Try to fix ACME path when renew (#33668) (#33693)
|
||||
* Fix mCaptcha bug (#33659) (#33661)
|
||||
* Git graph: don't show detached commits (#33645) (#33650)
|
||||
* Use MatchPhraseQuery for bleve code search (#33628)
|
||||
* Adjust appearence of commit status webhook (#33778) #33789
|
||||
* Upgrade golang net from 0.35.0 -> 0.36.0 (#33795) #33796
|
||||
|
||||
## [1.23.4](https://github.com/go-gitea/gitea/releases/tag/v1.23.4) - 2025-02-16
|
||||
|
||||
* SECURITY
|
||||
|
32
Makefile
32
Makefile
@ -73,6 +73,7 @@ EXTRA_GOFLAGS ?=
|
||||
MAKE_VERSION := $(shell "$(MAKE)" -v | cat | head -n 1)
|
||||
MAKE_EVIDENCE_DIR := .make_evidence
|
||||
|
||||
GOTESTFLAGS ?=
|
||||
ifeq ($(RACE_ENABLED),true)
|
||||
GOFLAGS += -race
|
||||
GOTESTFLAGS += -race
|
||||
@ -114,8 +115,6 @@ LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
|
||||
GO_TEST_PACKAGES ?= $(filter-out $(shell $(GO) list code.gitea.io/gitea/models/migrations/...) code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/))
|
||||
MIGRATE_TEST_PACKAGES ?= $(shell $(GO) list code.gitea.io/gitea/models/migrations/...)
|
||||
|
||||
FOMANTIC_WORK_DIR := web_src/fomantic
|
||||
|
||||
WEBPACK_SOURCES := $(shell find web_src/js web_src/css -type f)
|
||||
WEBPACK_CONFIGS := webpack.config.js tailwind.config.js
|
||||
WEBPACK_DEST := public/assets/js/index.js public/assets/css/index.css
|
||||
@ -139,7 +138,7 @@ TAGS_EVIDENCE := $(MAKE_EVIDENCE_DIR)/tags
|
||||
|
||||
TEST_TAGS ?= $(TAGS_SPLIT) sqlite sqlite_unlock_notify
|
||||
|
||||
TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMANTIC_WORK_DIR)/node_modules $(DIST) $(MAKE_EVIDENCE_DIR) $(AIR_TMP_DIR) $(GO_LICENSE_TMP_DIR)
|
||||
TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(DIST) $(MAKE_EVIDENCE_DIR) $(AIR_TMP_DIR) $(GO_LICENSE_TMP_DIR)
|
||||
|
||||
GO_DIRS := build cmd models modules routers services tests
|
||||
WEB_DIRS := web_src/js web_src/css
|
||||
@ -311,10 +310,10 @@ lint-frontend: lint-js lint-css ## lint frontend files
|
||||
lint-frontend-fix: lint-js-fix lint-css-fix ## lint frontend files and fix issues
|
||||
|
||||
.PHONY: lint-backend
|
||||
lint-backend: lint-go lint-go-vet lint-go-gopls lint-editorconfig ## lint backend files
|
||||
lint-backend: lint-go lint-go-gitea-vet lint-go-gopls lint-editorconfig ## lint backend files
|
||||
|
||||
.PHONY: lint-backend-fix
|
||||
lint-backend-fix: lint-go-fix lint-go-vet lint-editorconfig ## lint backend files and fix issues
|
||||
lint-backend-fix: lint-go-fix lint-go-gitea-vet lint-editorconfig ## lint backend files and fix issues
|
||||
|
||||
.PHONY: lint-js
|
||||
lint-js: node_modules ## lint js files
|
||||
@ -365,9 +364,9 @@ lint-go-windows:
|
||||
@GOOS= GOARCH= $(GO) install $(GOLANGCI_LINT_PACKAGE)
|
||||
golangci-lint run
|
||||
|
||||
.PHONY: lint-go-vet
|
||||
lint-go-vet: ## lint go files with vet
|
||||
@echo "Running go vet..."
|
||||
.PHONY: lint-go-gitea-vet
|
||||
lint-go-gitea-vet: ## lint go files with gitea-vet
|
||||
@echo "Running gitea-vet..."
|
||||
@GOOS= GOARCH= $(GO) build code.gitea.io/gitea-vet
|
||||
@$(GO) vet -vettool=gitea-vet ./...
|
||||
|
||||
@ -846,19 +845,6 @@ update-py: node-check | node_modules ## update py dependencies
|
||||
poetry install
|
||||
@touch .venv
|
||||
|
||||
.PHONY: fomantic
|
||||
fomantic: ## build fomantic files
|
||||
rm -rf $(FOMANTIC_WORK_DIR)/build
|
||||
cd $(FOMANTIC_WORK_DIR) && npm install --no-save
|
||||
cp -f $(FOMANTIC_WORK_DIR)/theme.config.less $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/theme.config
|
||||
cp -rf $(FOMANTIC_WORK_DIR)/_site $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/
|
||||
$(SED_INPLACE) -e 's/ overrideBrowserslist\r/ overrideBrowserslist: ["defaults"]\r/g' $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/tasks/config/tasks.js
|
||||
cd $(FOMANTIC_WORK_DIR) && npx gulp -f node_modules/fomantic-ui/gulpfile.js build
|
||||
# fomantic uses "touchstart" as click event for some browsers, it's not ideal, so we force fomantic to always use "click" as click event
|
||||
$(SED_INPLACE) -e 's/clickEvent[ \t]*=/clickEvent = "click", unstableClickEvent =/g' $(FOMANTIC_WORK_DIR)/build/semantic.js
|
||||
$(SED_INPLACE) -e 's/\r//g' $(FOMANTIC_WORK_DIR)/build/semantic.css $(FOMANTIC_WORK_DIR)/build/semantic.js
|
||||
rm -f $(FOMANTIC_WORK_DIR)/build/*.min.*
|
||||
|
||||
.PHONY: webpack
|
||||
webpack: $(WEBPACK_DEST) ## build webpack files
|
||||
|
||||
@ -905,10 +891,6 @@ update-translations:
|
||||
mv ./translations/*.ini ./options/locale/
|
||||
rmdir ./translations
|
||||
|
||||
.PHONY: generate-license
|
||||
generate-license: ## update license files
|
||||
$(GO) run build/generate-licenses.go
|
||||
|
||||
.PHONY: generate-gitignore
|
||||
generate-gitignore: ## update gitignore files
|
||||
$(GO) run build/generate-gitignores.go
|
||||
|
@ -1,176 +0,0 @@
|
||||
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//go:build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/build/license"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var (
|
||||
prefix = "gitea-licenses"
|
||||
url = "https://api.github.com/repos/spdx/license-list-data/tarball"
|
||||
githubApiToken = ""
|
||||
githubUsername = ""
|
||||
destination = ""
|
||||
)
|
||||
|
||||
flag.StringVar(&destination, "dest", "options/license/", "destination for the licenses")
|
||||
flag.StringVar(&githubUsername, "username", "", "github username")
|
||||
flag.StringVar(&githubApiToken, "token", "", "github api token")
|
||||
flag.Parse()
|
||||
|
||||
file, err := os.CreateTemp(os.TempDir(), prefix)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create temp file. %s", err)
|
||||
}
|
||||
|
||||
defer util.Remove(file.Name())
|
||||
|
||||
if err := os.RemoveAll(destination); err != nil {
|
||||
log.Fatalf("Cannot clean destination folder: %v", err)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(destination, 0o755); err != nil {
|
||||
log.Fatalf("Cannot create destination: %v", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to download archive. %s", err)
|
||||
}
|
||||
|
||||
if len(githubApiToken) > 0 && len(githubUsername) > 0 {
|
||||
req.SetBasicAuth(githubUsername, githubApiToken)
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to download archive. %s", err)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
if _, err := io.Copy(file, resp.Body); err != nil {
|
||||
log.Fatalf("Failed to copy archive to file. %s", err)
|
||||
}
|
||||
|
||||
if _, err := file.Seek(0, 0); err != nil {
|
||||
log.Fatalf("Failed to reset seek on archive. %s", err)
|
||||
}
|
||||
|
||||
gz, err := gzip.NewReader(file)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to gunzip the archive. %s", err)
|
||||
}
|
||||
|
||||
tr := tar.NewReader(gz)
|
||||
aliasesFiles := make(map[string][]string)
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to iterate archive. %s", err)
|
||||
}
|
||||
|
||||
if !strings.Contains(hdr.Name, "/text/") {
|
||||
continue
|
||||
}
|
||||
|
||||
if filepath.Ext(hdr.Name) != ".txt" {
|
||||
continue
|
||||
}
|
||||
|
||||
fileBaseName := filepath.Base(hdr.Name)
|
||||
licenseName := strings.TrimSuffix(fileBaseName, ".txt")
|
||||
|
||||
if strings.HasPrefix(fileBaseName, "README") {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(fileBaseName, "deprecated_") {
|
||||
continue
|
||||
}
|
||||
out, err := os.Create(path.Join(destination, licenseName))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create new file. %s", err)
|
||||
}
|
||||
|
||||
defer out.Close()
|
||||
|
||||
// some license files have same content, so we need to detect these files and create a convert map into a json file
|
||||
// Later we use this convert map to avoid adding same license content with different license name
|
||||
h := md5.New()
|
||||
// calculate md5 and write file in the same time
|
||||
r := io.TeeReader(tr, h)
|
||||
if _, err := io.Copy(out, r); err != nil {
|
||||
log.Fatalf("Failed to write new file. %s", err)
|
||||
} else {
|
||||
fmt.Printf("Written %s\n", out.Name())
|
||||
|
||||
md5 := hex.EncodeToString(h.Sum(nil))
|
||||
aliasesFiles[md5] = append(aliasesFiles[md5], licenseName)
|
||||
}
|
||||
}
|
||||
|
||||
// generate convert license name map
|
||||
licenseAliases := make(map[string]string)
|
||||
for _, fileNames := range aliasesFiles {
|
||||
if len(fileNames) > 1 {
|
||||
licenseName := license.GetLicenseNameFromAliases(fileNames)
|
||||
if licenseName == "" {
|
||||
// license name should not be empty as expected
|
||||
// if it is empty, we need to rewrite the logic of GetLicenseNameFromAliases
|
||||
log.Fatalf("GetLicenseNameFromAliases: license name is empty")
|
||||
}
|
||||
for _, fileName := range fileNames {
|
||||
licenseAliases[fileName] = licenseName
|
||||
}
|
||||
}
|
||||
}
|
||||
// save convert license name map to file
|
||||
b, err := json.Marshal(licenseAliases)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create json bytes. %s", err)
|
||||
}
|
||||
|
||||
licenseAliasesDestination := filepath.Join(destination, "etc", "license-aliases.json")
|
||||
if err := os.MkdirAll(filepath.Dir(licenseAliasesDestination), 0o755); err != nil {
|
||||
log.Fatalf("Failed to create directory for license aliases json file. %s", err)
|
||||
}
|
||||
|
||||
f, err := os.Create(licenseAliasesDestination)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create license aliases json file. %s", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if _, err = f.Write(b); err != nil {
|
||||
log.Fatalf("Failed to write license aliases json file. %s", err)
|
||||
}
|
||||
|
||||
fmt.Println("Done")
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package license
|
||||
|
||||
import "strings"
|
||||
|
||||
func GetLicenseNameFromAliases(fnl []string) string {
|
||||
if len(fnl) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
shortestItem := func(list []string) string {
|
||||
s := list[0]
|
||||
for _, l := range list[1:] {
|
||||
if len(l) < len(s) {
|
||||
s = l
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
allHasPrefix := func(list []string, s string) bool {
|
||||
for _, l := range list {
|
||||
if !strings.HasPrefix(l, s) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
sl := shortestItem(fnl)
|
||||
slv := strings.Split(sl, "-")
|
||||
var result string
|
||||
for i := len(slv); i >= 0; i-- {
|
||||
result = strings.Join(slv[:i], "-")
|
||||
if allHasPrefix(fnl, result) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package license
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetLicenseNameFromAliases(t *testing.T) {
|
||||
tests := []struct {
|
||||
target string
|
||||
inputs []string
|
||||
}{
|
||||
{
|
||||
// real case which you can find in license-aliases.json
|
||||
target: "AGPL-1.0",
|
||||
inputs: []string{
|
||||
"AGPL-1.0-only",
|
||||
"AGPL-1.0-or-late",
|
||||
},
|
||||
},
|
||||
{
|
||||
target: "",
|
||||
inputs: []string{
|
||||
"APSL-1.0",
|
||||
"AGPL-1.0-only",
|
||||
"AGPL-1.0-or-late",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
result := GetLicenseNameFromAliases(tt.inputs)
|
||||
assert.Equal(t, result, tt.target)
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
golog "log"
|
||||
"os"
|
||||
@ -130,8 +131,8 @@ func runRecreateTable(ctx *cli.Context) error {
|
||||
}
|
||||
recreateTables := migrate_base.RecreateTables(beans...)
|
||||
|
||||
return db.InitEngineWithMigration(stdCtx, func(x *xorm.Engine) error {
|
||||
if err := migrations.EnsureUpToDate(x); err != nil {
|
||||
return db.InitEngineWithMigration(stdCtx, func(ctx context.Context, x *xorm.Engine) error {
|
||||
if err := migrations.EnsureUpToDate(ctx, x); err != nil {
|
||||
return err
|
||||
}
|
||||
return recreateTables(x)
|
||||
|
@ -316,7 +316,7 @@ func runHookPostReceive(c *cli.Context) error {
|
||||
setup(ctx, c.Bool("debug"))
|
||||
|
||||
// First of all run update-server-info no matter what
|
||||
if _, _, err := git.NewCommand(ctx, "update-server-info").RunStdString(nil); err != nil {
|
||||
if _, _, err := git.NewCommand("update-server-info").RunStdString(ctx, nil); err != nil {
|
||||
return fmt.Errorf("Failed to call 'git update-server-info': %w", err)
|
||||
}
|
||||
|
||||
|
@ -7,9 +7,9 @@ import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/migrations"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/services/versioned_migration"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@ -36,7 +36,7 @@ func runMigrate(ctx *cli.Context) error {
|
||||
log.Info("Log path: %s", setting.Log.RootPath)
|
||||
log.Info("Configuration file: %s", setting.CustomConf)
|
||||
|
||||
if err := db.InitEngineWithMigration(context.Background(), migrations.Migrate); err != nil {
|
||||
if err := db.InitEngineWithMigration(context.Background(), versioned_migration.Migrate); err != nil {
|
||||
log.Fatal("Failed to initialize ORM engine: %v", err)
|
||||
return err
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ import (
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
"code.gitea.io/gitea/models/migrations"
|
||||
packages_model "code.gitea.io/gitea/models/packages"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@ -21,6 +20,7 @@ import (
|
||||
packages_module "code.gitea.io/gitea/modules/packages"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/storage"
|
||||
"code.gitea.io/gitea/services/versioned_migration"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@ -227,7 +227,7 @@ func runMigrateStorage(ctx *cli.Context) error {
|
||||
log.Info("Log path: %s", setting.Log.RootPath)
|
||||
log.Info("Configuration file: %s", setting.CustomConf)
|
||||
|
||||
if err := db.InitEngineWithMigration(context.Background(), migrations.Migrate); err != nil {
|
||||
if err := db.InitEngineWithMigration(context.Background(), versioned_migration.Migrate); err != nil {
|
||||
log.Fatal("Failed to initialize ORM engine: %v", err)
|
||||
return err
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/process"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/caddyserver/certmagic"
|
||||
)
|
||||
@ -68,9 +69,15 @@ func runACME(listenAddr string, m http.Handler) error {
|
||||
// And one more thing, no idea why we should set the global default variables here
|
||||
// But it seems that the current ACME code needs these global variables to make renew work.
|
||||
// Otherwise, "renew" will use incorrect storage path
|
||||
oldDefaultACME := certmagic.DefaultACME
|
||||
certmagic.Default.Storage = &certmagic.FileStorage{Path: setting.AcmeLiveDirectory}
|
||||
certmagic.DefaultACME = certmagic.ACMEIssuer{
|
||||
CA: setting.AcmeURL,
|
||||
// try to use the default values provided by DefaultACME
|
||||
CA: util.IfZero(setting.AcmeURL, oldDefaultACME.CA),
|
||||
TestCA: oldDefaultACME.TestCA,
|
||||
Logger: oldDefaultACME.Logger,
|
||||
HTTPProxy: oldDefaultACME.HTTPProxy,
|
||||
|
||||
TrustedRoots: certPool,
|
||||
Email: setting.AcmeEmail,
|
||||
Agreed: setting.AcmeTOS,
|
||||
|
@ -1294,6 +1294,9 @@ LEVEL = Info
|
||||
;; Leave it empty to allow users to select any theme from "{CustomPath}/public/assets/css/theme-*.css"
|
||||
;THEMES =
|
||||
;;
|
||||
;; The icons for file list (basic/material), this is a temporary option which will be replaced by a user setting in the future.
|
||||
;FILE_ICON_THEME = material
|
||||
;;
|
||||
;; All available reactions users can choose on issues/prs and comments.
|
||||
;; Values can be emoji alias (:smile:) or a unicode emoji.
|
||||
;; For custom reactions, add a tightly cropped square image to public/assets/img/emoji/reaction_name.png
|
||||
@ -1767,6 +1770,9 @@ LEVEL = Info
|
||||
;;
|
||||
;; convert \r\n to \n for Sendmail
|
||||
;SENDMAIL_CONVERT_CRLF = true
|
||||
;;
|
||||
;; convert links of attached images to inline images. Only for images hosted in this gitea instance.
|
||||
;EMBED_ATTACHMENT_IMAGES = false
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
2
go.mod
2
go.mod
@ -119,7 +119,7 @@ require (
|
||||
gitlab.com/gitlab-org/api/client-go v0.123.0
|
||||
golang.org/x/crypto v0.35.0
|
||||
golang.org/x/image v0.24.0
|
||||
golang.org/x/net v0.35.0
|
||||
golang.org/x/net v0.36.0
|
||||
golang.org/x/oauth2 v0.27.0
|
||||
golang.org/x/sync v0.11.0
|
||||
golang.org/x/sys v0.30.0
|
||||
|
4
go.sum
4
go.sum
@ -867,8 +867,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
|
||||
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
|
||||
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
|
||||
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -194,7 +194,7 @@ func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) err
|
||||
|
||||
// CancelPreviousJobs cancels all previous jobs of the same repository, reference, workflow, and event.
|
||||
// It's useful when a new run is triggered, and all previous runs needn't be continued anymore.
|
||||
func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID string, event webhook_module.HookEventType) error {
|
||||
func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID string, event webhook_module.HookEventType) ([]*ActionRunJob, error) {
|
||||
// Find all runs in the specified repository, reference, and workflow with non-final status
|
||||
runs, total, err := db.FindAndCount[ActionRun](ctx, FindRunOptions{
|
||||
RepoID: repoID,
|
||||
@ -204,14 +204,16 @@ func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID strin
|
||||
Status: []Status{StatusRunning, StatusWaiting, StatusBlocked},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If there are no runs found, there's no need to proceed with cancellation, so return nil.
|
||||
if total == 0 {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
cancelledJobs := make([]*ActionRunJob, 0, total)
|
||||
|
||||
// Iterate over each found run and cancel its associated jobs.
|
||||
for _, run := range runs {
|
||||
// Find all jobs associated with the current run.
|
||||
@ -219,7 +221,7 @@ func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID strin
|
||||
RunID: run.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
return cancelledJobs, err
|
||||
}
|
||||
|
||||
// Iterate over each job and attempt to cancel it.
|
||||
@ -238,27 +240,29 @@ func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID strin
|
||||
// Update the job's status and stopped time in the database.
|
||||
n, err := UpdateRunJob(ctx, job, builder.Eq{"task_id": 0}, "status", "stopped")
|
||||
if err != nil {
|
||||
return err
|
||||
return cancelledJobs, err
|
||||
}
|
||||
|
||||
// If the update affected 0 rows, it means the job has changed in the meantime, so we need to try again.
|
||||
if n == 0 {
|
||||
return fmt.Errorf("job has changed, try again")
|
||||
return cancelledJobs, fmt.Errorf("job has changed, try again")
|
||||
}
|
||||
|
||||
cancelledJobs = append(cancelledJobs, job)
|
||||
// Continue with the next job.
|
||||
continue
|
||||
}
|
||||
|
||||
// If the job has an associated task, try to stop the task, effectively cancelling the job.
|
||||
if err := StopTask(ctx, job.TaskID, StatusCancelled); err != nil {
|
||||
return err
|
||||
return cancelledJobs, err
|
||||
}
|
||||
cancelledJobs = append(cancelledJobs, job)
|
||||
}
|
||||
}
|
||||
|
||||
// Return nil to indicate successful cancellation of all running and waiting jobs.
|
||||
return nil
|
||||
return cancelledJobs, nil
|
||||
}
|
||||
|
||||
// InsertRun inserts a run
|
||||
|
@ -337,3 +337,17 @@ func FixRunnersWithoutBelongingRepo(ctx context.Context) (int64, error) {
|
||||
}
|
||||
return res.RowsAffected()
|
||||
}
|
||||
|
||||
func CountWrongRepoLevelRunners(ctx context.Context) (int64, error) {
|
||||
var result int64
|
||||
_, err := db.GetEngine(ctx).SQL("SELECT count(`id`) FROM `action_runner` WHERE `repo_id` > 0 AND `owner_id` > 0").Get(&result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func UpdateWrongRepoLevelRunners(ctx context.Context) (int64, error) {
|
||||
result, err := db.GetEngine(ctx).Exec("UPDATE `action_runner` SET `owner_id` = 0 WHERE `repo_id` > 0 AND `owner_id` > 0")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected()
|
||||
}
|
||||
|
@ -43,15 +43,12 @@ func init() {
|
||||
// GetSchedulesMapByIDs returns the schedules by given id slice.
|
||||
func GetSchedulesMapByIDs(ctx context.Context, ids []int64) (map[int64]*ActionSchedule, error) {
|
||||
schedules := make(map[int64]*ActionSchedule, len(ids))
|
||||
if len(ids) == 0 {
|
||||
return schedules, nil
|
||||
}
|
||||
return schedules, db.GetEngine(ctx).In("id", ids).Find(&schedules)
|
||||
}
|
||||
|
||||
// GetReposMapByIDs returns the repos by given id slice.
|
||||
func GetReposMapByIDs(ctx context.Context, ids []int64) (map[int64]*repo_model.Repository, error) {
|
||||
repos := make(map[int64]*repo_model.Repository, len(ids))
|
||||
return repos, db.GetEngine(ctx).In("id", ids).Find(&repos)
|
||||
}
|
||||
|
||||
// CreateScheduleTask creates new schedule task.
|
||||
func CreateScheduleTask(ctx context.Context, rows []*ActionSchedule) error {
|
||||
// Return early if there are no rows to insert
|
||||
@ -120,21 +117,22 @@ func DeleteScheduleTaskByRepo(ctx context.Context, id int64) error {
|
||||
return committer.Commit()
|
||||
}
|
||||
|
||||
func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository) error {
|
||||
func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository) ([]*ActionRunJob, error) {
|
||||
// If actions disabled when there is schedule task, this will remove the outdated schedule tasks
|
||||
// There is no other place we can do this because the app.ini will be changed manually
|
||||
if err := DeleteScheduleTaskByRepo(ctx, repo.ID); err != nil {
|
||||
return fmt.Errorf("DeleteCronTaskByRepo: %v", err)
|
||||
return nil, fmt.Errorf("DeleteCronTaskByRepo: %v", err)
|
||||
}
|
||||
// cancel running cron jobs of this repository and delete old schedules
|
||||
if err := CancelPreviousJobs(
|
||||
jobs, err := CancelPreviousJobs(
|
||||
ctx,
|
||||
repo.ID,
|
||||
repo.DefaultBranch,
|
||||
"",
|
||||
webhook_module.HookEventSchedule,
|
||||
); err != nil {
|
||||
return fmt.Errorf("CancelPreviousJobs: %v", err)
|
||||
)
|
||||
if err != nil {
|
||||
return jobs, fmt.Errorf("CancelPreviousJobs: %v", err)
|
||||
}
|
||||
return nil
|
||||
return jobs, nil
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ func (specs SpecList) LoadSchedules(ctx context.Context) error {
|
||||
}
|
||||
|
||||
repoIDs := specs.GetRepoIDs()
|
||||
repos, err := GetReposMapByIDs(ctx, repoIDs)
|
||||
repos, err := repo_model.GetRepositoriesMapByIDs(ctx, repoIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -147,3 +147,17 @@ func GetVariablesOfRun(ctx context.Context, run *ActionRun) (map[string]string,
|
||||
|
||||
return variables, nil
|
||||
}
|
||||
|
||||
func CountWrongRepoLevelVariables(ctx context.Context) (int64, error) {
|
||||
var result int64
|
||||
_, err := db.GetEngine(ctx).SQL("SELECT count(`id`) FROM `action_variable` WHERE `repo_id` > 0 AND `owner_id` > 0").Get(&result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func UpdateWrongRepoLevelVariables(ctx context.Context) (int64, error) {
|
||||
result, err := db.GetEngine(ctx).Exec("UPDATE `action_variable` SET `owner_id` = 0 WHERE `repo_id` > 0 AND `owner_id` > 0")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected()
|
||||
}
|
||||
|
@ -16,9 +16,7 @@ import (
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
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/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
@ -200,15 +198,13 @@ func (a *Action) LoadActUser(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Action) LoadRepo(ctx context.Context) {
|
||||
func (a *Action) LoadRepo(ctx context.Context) error {
|
||||
if a.Repo != nil {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
var err error
|
||||
a.Repo, err = repo_model.GetRepositoryByID(ctx, a.RepoID)
|
||||
if err != nil {
|
||||
log.Error("repo_model.GetRepositoryByID(%d): %v", a.RepoID, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// GetActFullName gets the action's user full name.
|
||||
@ -250,7 +246,7 @@ func (a *Action) GetActDisplayNameTitle(ctx context.Context) string {
|
||||
|
||||
// GetRepoUserName returns the name of the action repository owner.
|
||||
func (a *Action) GetRepoUserName(ctx context.Context) string {
|
||||
a.LoadRepo(ctx)
|
||||
_ = a.LoadRepo(ctx)
|
||||
if a.Repo == nil {
|
||||
return "(non-existing-repo)"
|
||||
}
|
||||
@ -265,7 +261,7 @@ func (a *Action) ShortRepoUserName(ctx context.Context) string {
|
||||
|
||||
// GetRepoName returns the name of the action repository.
|
||||
func (a *Action) GetRepoName(ctx context.Context) string {
|
||||
a.LoadRepo(ctx)
|
||||
_ = a.LoadRepo(ctx)
|
||||
if a.Repo == nil {
|
||||
return "(non-existing-repo)"
|
||||
}
|
||||
@ -529,8 +525,8 @@ func ActivityQueryCondition(ctx context.Context, opts GetFeedsOptions) (builder.
|
||||
}
|
||||
|
||||
if opts.RequestedTeam != nil {
|
||||
env := repo_model.AccessibleTeamReposEnv(ctx, organization.OrgFromUser(opts.RequestedUser), opts.RequestedTeam)
|
||||
teamRepoIDs, err := env.RepoIDs(1, opts.RequestedUser.NumRepos)
|
||||
env := repo_model.AccessibleTeamReposEnv(organization.OrgFromUser(opts.RequestedUser), opts.RequestedTeam)
|
||||
teamRepoIDs, err := env.RepoIDs(ctx, 1, opts.RequestedUser.NumRepos)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetTeamRepositories: %w", err)
|
||||
}
|
||||
@ -567,130 +563,6 @@ func DeleteOldActions(ctx context.Context, olderThan time.Duration) (err error)
|
||||
return err
|
||||
}
|
||||
|
||||
// NotifyWatchers creates batch of actions for every watcher.
|
||||
// It could insert duplicate actions for a repository action, like this:
|
||||
// * Original action: UserID=1 (the real actor), ActUserID=1
|
||||
// * Organization action: UserID=100 (the repo's org), ActUserID=1
|
||||
// * Watcher action: UserID=20 (a user who is watching a repo), ActUserID=1
|
||||
func NotifyWatchers(ctx context.Context, actions ...*Action) error {
|
||||
var watchers []*repo_model.Watch
|
||||
var repo *repo_model.Repository
|
||||
var err error
|
||||
var permCode []bool
|
||||
var permIssue []bool
|
||||
var permPR []bool
|
||||
|
||||
e := db.GetEngine(ctx)
|
||||
|
||||
for _, act := range actions {
|
||||
repoChanged := repo == nil || repo.ID != act.RepoID
|
||||
|
||||
if repoChanged {
|
||||
// Add feeds for user self and all watchers.
|
||||
watchers, err = repo_model.GetWatchers(ctx, act.RepoID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get watchers: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Add feed for actioner.
|
||||
act.UserID = act.ActUserID
|
||||
if _, err = e.Insert(act); err != nil {
|
||||
return fmt.Errorf("insert new actioner: %w", err)
|
||||
}
|
||||
|
||||
if repoChanged {
|
||||
act.LoadRepo(ctx)
|
||||
repo = act.Repo
|
||||
|
||||
// check repo owner exist.
|
||||
if err := act.Repo.LoadOwner(ctx); err != nil {
|
||||
return fmt.Errorf("can't get repo owner: %w", err)
|
||||
}
|
||||
} else if act.Repo == nil {
|
||||
act.Repo = repo
|
||||
}
|
||||
|
||||
// Add feed for organization
|
||||
if act.Repo.Owner.IsOrganization() && act.ActUserID != act.Repo.Owner.ID {
|
||||
act.ID = 0
|
||||
act.UserID = act.Repo.Owner.ID
|
||||
if err = db.Insert(ctx, act); err != nil {
|
||||
return fmt.Errorf("insert new actioner: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if repoChanged {
|
||||
permCode = make([]bool, len(watchers))
|
||||
permIssue = make([]bool, len(watchers))
|
||||
permPR = make([]bool, len(watchers))
|
||||
for i, watcher := range watchers {
|
||||
user, err := user_model.GetUserByID(ctx, watcher.UserID)
|
||||
if err != nil {
|
||||
permCode[i] = false
|
||||
permIssue[i] = false
|
||||
permPR[i] = false
|
||||
continue
|
||||
}
|
||||
perm, err := access_model.GetUserRepoPermission(ctx, repo, user)
|
||||
if err != nil {
|
||||
permCode[i] = false
|
||||
permIssue[i] = false
|
||||
permPR[i] = false
|
||||
continue
|
||||
}
|
||||
permCode[i] = perm.CanRead(unit.TypeCode)
|
||||
permIssue[i] = perm.CanRead(unit.TypeIssues)
|
||||
permPR[i] = perm.CanRead(unit.TypePullRequests)
|
||||
}
|
||||
}
|
||||
|
||||
for i, watcher := range watchers {
|
||||
if act.ActUserID == watcher.UserID {
|
||||
continue
|
||||
}
|
||||
act.ID = 0
|
||||
act.UserID = watcher.UserID
|
||||
act.Repo.Units = nil
|
||||
|
||||
switch act.OpType {
|
||||
case ActionCommitRepo, ActionPushTag, ActionDeleteTag, ActionPublishRelease, ActionDeleteBranch:
|
||||
if !permCode[i] {
|
||||
continue
|
||||
}
|
||||
case ActionCreateIssue, ActionCommentIssue, ActionCloseIssue, ActionReopenIssue:
|
||||
if !permIssue[i] {
|
||||
continue
|
||||
}
|
||||
case ActionCreatePullRequest, ActionCommentPull, ActionMergePullRequest, ActionClosePullRequest, ActionReopenPullRequest, ActionAutoMergePullRequest:
|
||||
if !permPR[i] {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if err = db.Insert(ctx, act); err != nil {
|
||||
return fmt.Errorf("insert new action: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NotifyWatchersActions creates batch of actions for every watcher.
|
||||
func NotifyWatchersActions(ctx context.Context, acts []*Action) error {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer committer.Close()
|
||||
for _, act := range acts {
|
||||
if err := NotifyWatchers(ctx, act); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return committer.Commit()
|
||||
}
|
||||
|
||||
// DeleteIssueActions delete all actions related with issueID
|
||||
func DeleteIssueActions(ctx context.Context, repoID, issueID, issueIndex int64) error {
|
||||
// delete actions assigned to this issue
|
||||
|
@ -82,43 +82,6 @@ func TestActivityReadable(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotifyWatchers(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
action := &activities_model.Action{
|
||||
ActUserID: 8,
|
||||
RepoID: 1,
|
||||
OpType: activities_model.ActionStarRepo,
|
||||
}
|
||||
assert.NoError(t, activities_model.NotifyWatchers(db.DefaultContext, action))
|
||||
|
||||
// One watchers are inactive, thus action is only created for user 8, 1, 4, 11
|
||||
unittest.AssertExistsAndLoadBean(t, &activities_model.Action{
|
||||
ActUserID: action.ActUserID,
|
||||
UserID: 8,
|
||||
RepoID: action.RepoID,
|
||||
OpType: action.OpType,
|
||||
})
|
||||
unittest.AssertExistsAndLoadBean(t, &activities_model.Action{
|
||||
ActUserID: action.ActUserID,
|
||||
UserID: 1,
|
||||
RepoID: action.RepoID,
|
||||
OpType: action.OpType,
|
||||
})
|
||||
unittest.AssertExistsAndLoadBean(t, &activities_model.Action{
|
||||
ActUserID: action.ActUserID,
|
||||
UserID: 4,
|
||||
RepoID: action.RepoID,
|
||||
OpType: action.OpType,
|
||||
})
|
||||
unittest.AssertExistsAndLoadBean(t, &activities_model.Action{
|
||||
ActUserID: action.ActUserID,
|
||||
UserID: 11,
|
||||
RepoID: action.RepoID,
|
||||
OpType: action.OpType,
|
||||
})
|
||||
}
|
||||
|
||||
func TestConsistencyUpdateAction(t *testing.T) {
|
||||
if !setting.Database.Type.IsSQLite3() {
|
||||
t.Skip("Test is only for SQLite database.")
|
||||
|
@ -25,7 +25,7 @@ func (err ErrKeyUnableVerify) Error() string {
|
||||
}
|
||||
|
||||
// ErrKeyIsPrivate is returned when the provided key is a private key not a public key
|
||||
var ErrKeyIsPrivate = util.NewSilentWrapErrorf(util.ErrInvalidArgument, "the provided key is a private key")
|
||||
var ErrKeyIsPrivate = util.ErrorWrap(util.ErrInvalidArgument, "the provided key is a private key")
|
||||
|
||||
// ErrKeyNotExist represents a "KeyNotExist" kind of error.
|
||||
type ErrKeyNotExist struct {
|
||||
|
@ -289,6 +289,9 @@ func FindIDs(ctx context.Context, tableName, idCol string, cond builder.Cond) ([
|
||||
// DecrByIDs decreases the given column for entities of the "bean" type with one of the given ids by one
|
||||
// Timestamps of the entities won't be updated
|
||||
func DecrByIDs(ctx context.Context, ids []int64, decrCol string, bean any) error {
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
_, err := GetEngine(ctx).Decr(decrCol).In("id", ids).NoAutoCondition().NoAutoTime().Update(bean)
|
||||
return err
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ func (h *EngineHook) AfterProcess(c *contexts.ContextHook) error {
|
||||
// 8 is the amount of skips passed to runtime.Caller, so that in the log the correct function
|
||||
// is being displayed (the function that ultimately wants to execute the query in the code)
|
||||
// instead of the function of the slow query hook being called.
|
||||
h.Logger.Log(8, log.WARN, "[Slow SQL Query] %s %v - %v", c.SQL, c.Args, c.ExecuteTime)
|
||||
h.Logger.Log(8, &log.Event{Level: log.WARN}, "[Slow SQL Query] %s %v - %v", c.SQL, c.Args, c.ExecuteTime)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ func UnsetDefaultEngine() {
|
||||
// When called from the "doctor" command, the migration function is a version check
|
||||
// that prevents the doctor from fixing anything in the database if the migration level
|
||||
// is different from the expected value.
|
||||
func InitEngineWithMigration(ctx context.Context, migrateFunc func(*xorm.Engine) error) (err error) {
|
||||
func InitEngineWithMigration(ctx context.Context, migrateFunc func(context.Context, *xorm.Engine) error) (err error) {
|
||||
if err = InitEngine(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -122,7 +122,7 @@ func InitEngineWithMigration(ctx context.Context, migrateFunc func(*xorm.Engine)
|
||||
// Installation should only be being re-run if users want to recover an old database.
|
||||
// However, we should think carefully about should we support re-install on an installed instance,
|
||||
// as there may be other problems due to secret reinitialization.
|
||||
if err = migrateFunc(xormEngine); err != nil {
|
||||
if err = migrateFunc(ctx, xormEngine); err != nil {
|
||||
return fmt.Errorf("migrate: %w", err)
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ const stackLevel = 8
|
||||
|
||||
// Log a message with defined skip and at logging level
|
||||
func (l *XORMLogBridge) Log(skip int, level log.Level, format string, v ...any) {
|
||||
l.logger.Log(skip+1, level, format, v...)
|
||||
l.logger.Log(skip+1, &log.Event{Level: level}, format, v...)
|
||||
}
|
||||
|
||||
// Debug show debug log
|
||||
|
@ -77,7 +77,7 @@ func (err ErrNameCharsNotAllowed) Unwrap() error {
|
||||
func IsUsableName(reservedNames, reservedPatterns []string, name string) error {
|
||||
name = strings.TrimSpace(strings.ToLower(name))
|
||||
if utf8.RuneCountInString(name) == 0 {
|
||||
return util.SilentWrap{Message: "name is empty", Err: util.ErrInvalidArgument}
|
||||
return util.NewInvalidArgumentErrorf("name is empty")
|
||||
}
|
||||
|
||||
for i := range reservedNames {
|
||||
|
@ -595,6 +595,9 @@ func GetIssueByID(ctx context.Context, id int64) (*Issue, error) {
|
||||
// If keepOrder is true, the order of the returned issues will be the same as the given IDs.
|
||||
func GetIssuesByIDs(ctx context.Context, issueIDs []int64, keepOrder ...bool) (IssueList, error) {
|
||||
issues := make([]*Issue, 0, len(issueIDs))
|
||||
if len(issueIDs) == 0 {
|
||||
return issues, nil
|
||||
}
|
||||
|
||||
if err := db.GetEngine(ctx).In("id", issueIDs).Find(&issues); err != nil {
|
||||
return nil, err
|
||||
|
@ -299,6 +299,9 @@ func GetLabelByID(ctx context.Context, labelID int64) (*Label, error) {
|
||||
// GetLabelsByIDs returns a list of labels by IDs
|
||||
func GetLabelsByIDs(ctx context.Context, labelIDs []int64, cols ...string) ([]*Label, error) {
|
||||
labels := make([]*Label, 0, len(labelIDs))
|
||||
if len(labelIDs) == 0 {
|
||||
return labels, nil
|
||||
}
|
||||
return labels, db.GetEngine(ctx).Table("label").
|
||||
In("id", labelIDs).
|
||||
Asc("name").
|
||||
@ -375,6 +378,9 @@ func BuildLabelNamesIssueIDsCondition(labelNames []string) *builder.Builder {
|
||||
// it silently ignores label IDs that do not belong to the repository.
|
||||
func GetLabelsInRepoByIDs(ctx context.Context, repoID int64, labelIDs []int64) ([]*Label, error) {
|
||||
labels := make([]*Label, 0, len(labelIDs))
|
||||
if len(labelIDs) == 0 {
|
||||
return labels, nil
|
||||
}
|
||||
return labels, db.GetEngine(ctx).
|
||||
Where("repo_id = ?", repoID).
|
||||
In("id", labelIDs).
|
||||
@ -447,6 +453,9 @@ func GetLabelInOrgByID(ctx context.Context, orgID, labelID int64) (*Label, error
|
||||
// it silently ignores label IDs that do not belong to the organization.
|
||||
func GetLabelsInOrgByIDs(ctx context.Context, orgID int64, labelIDs []int64) ([]*Label, error) {
|
||||
labels := make([]*Label, 0, len(labelIDs))
|
||||
if len(labelIDs) == 0 {
|
||||
return labels, nil
|
||||
}
|
||||
return labels, db.GetEngine(ctx).
|
||||
Where("org_id = ?", orgID).
|
||||
In("id", labelIDs).
|
||||
|
@ -61,7 +61,7 @@ func listPullRequestStatement(ctx context.Context, baseRepoID int64, opts *PullR
|
||||
}
|
||||
|
||||
// GetUnmergedPullRequestsByHeadInfo returns all pull requests that are open and has not been merged
|
||||
func GetUnmergedPullRequestsByHeadInfo(ctx context.Context, repoID int64, branch string) ([]*PullRequest, error) {
|
||||
func GetUnmergedPullRequestsByHeadInfo(ctx context.Context, repoID int64, branch string) (PullRequestList, error) {
|
||||
prs := make([]*PullRequest, 0, 2)
|
||||
sess := db.GetEngine(ctx).
|
||||
Join("INNER", "issue", "issue.id = pull_request.issue_id").
|
||||
@ -116,7 +116,7 @@ func HasUnmergedPullRequestsByHeadInfo(ctx context.Context, repoID int64, branch
|
||||
|
||||
// GetUnmergedPullRequestsByBaseInfo returns all pull requests that are open and has not been merged
|
||||
// by given base information (repo and branch).
|
||||
func GetUnmergedPullRequestsByBaseInfo(ctx context.Context, repoID int64, branch string) ([]*PullRequest, error) {
|
||||
func GetUnmergedPullRequestsByBaseInfo(ctx context.Context, repoID int64, branch string) (PullRequestList, error) {
|
||||
prs := make([]*PullRequest, 0, 2)
|
||||
return prs, db.GetEngine(ctx).
|
||||
Where("base_repo_id=? AND base_branch=? AND has_merged=? AND issue.is_closed=?",
|
||||
|
@ -16,11 +16,11 @@ import (
|
||||
func TestPullRequestList_LoadAttributes(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
prs := []*issues_model.PullRequest{
|
||||
prs := issues_model.PullRequestList{
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}),
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}),
|
||||
}
|
||||
assert.NoError(t, issues_model.PullRequestList(prs).LoadAttributes(db.DefaultContext))
|
||||
assert.NoError(t, prs.LoadAttributes(db.DefaultContext))
|
||||
for _, pr := range prs {
|
||||
assert.NotNil(t, pr.Issue)
|
||||
assert.Equal(t, pr.IssueID, pr.Issue.ID)
|
||||
@ -32,11 +32,11 @@ func TestPullRequestList_LoadAttributes(t *testing.T) {
|
||||
func TestPullRequestList_LoadReviewCommentsCounts(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
prs := []*issues_model.PullRequest{
|
||||
prs := issues_model.PullRequestList{
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}),
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}),
|
||||
}
|
||||
reviewComments, err := issues_model.PullRequestList(prs).LoadReviewCommentsCounts(db.DefaultContext)
|
||||
reviewComments, err := prs.LoadReviewCommentsCounts(db.DefaultContext)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, reviewComments, 2)
|
||||
for _, pr := range prs {
|
||||
@ -47,11 +47,11 @@ func TestPullRequestList_LoadReviewCommentsCounts(t *testing.T) {
|
||||
func TestPullRequestList_LoadReviews(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
prs := []*issues_model.PullRequest{
|
||||
prs := issues_model.PullRequestList{
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}),
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}),
|
||||
}
|
||||
reviewList, err := issues_model.PullRequestList(prs).LoadReviews(db.DefaultContext)
|
||||
reviewList, err := prs.LoadReviews(db.DefaultContext)
|
||||
assert.NoError(t, err)
|
||||
// 1, 7, 8, 9, 10, 22
|
||||
assert.Len(t, reviewList, 6)
|
||||
|
@ -374,6 +374,7 @@ func prepareMigrationTasks() []*migration {
|
||||
// Gitea 1.23.0-rc0 ends at migration ID number 311 (database version 312)
|
||||
newMigration(312, "Add DeleteBranchAfterMerge to AutoMerge", v1_24.AddDeleteBranchAfterMergeForAutoMerge),
|
||||
newMigration(313, "Move PinOrder from issue table to a new table issue_pin", v1_24.MovePinOrderToTableIssuePin),
|
||||
newMigration(314, "Update OwnerID as zero for repository level action tables", v1_24.UpdateOwnerIDOfRepoLevelActionsTables),
|
||||
}
|
||||
return preparedMigrations
|
||||
}
|
||||
@ -412,7 +413,7 @@ func ExpectedDBVersion() int64 {
|
||||
}
|
||||
|
||||
// EnsureUpToDate will check if the db is at the correct version
|
||||
func EnsureUpToDate(x *xorm.Engine) error {
|
||||
func EnsureUpToDate(ctx context.Context, x *xorm.Engine) error {
|
||||
currentDB, err := GetCurrentDBVersion(x)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -82,17 +82,17 @@ func FixMergeBase(x *xorm.Engine) error {
|
||||
|
||||
if !pr.HasMerged {
|
||||
var err error
|
||||
pr.MergeBase, _, err = git.NewCommand(git.DefaultContext, "merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).RunStdString(&git.RunOpts{Dir: repoPath})
|
||||
pr.MergeBase, _, err = git.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
var err2 error
|
||||
pr.MergeBase, _, err2 = git.NewCommand(git.DefaultContext, "rev-parse").AddDynamicArguments(git.BranchPrefix + pr.BaseBranch).RunStdString(&git.RunOpts{Dir: repoPath})
|
||||
pr.MergeBase, _, err2 = git.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix+pr.BaseBranch).RunStdString(git.DefaultContext, &git.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(git.DefaultContext, "rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(&git.RunOpts{Dir: repoPath})
|
||||
parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(git.DefaultContext, &git.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
|
||||
@ -104,9 +104,9 @@ func FixMergeBase(x *xorm.Engine) error {
|
||||
|
||||
refs := append([]string{}, parents[1:]...)
|
||||
refs = append(refs, gitRefName)
|
||||
cmd := git.NewCommand(git.DefaultContext, "merge-base").AddDashesAndList(refs...)
|
||||
cmd := git.NewCommand("merge-base").AddDashesAndList(refs...)
|
||||
|
||||
pr.MergeBase, _, err = cmd.RunStdString(&git.RunOpts{Dir: repoPath})
|
||||
pr.MergeBase, _, err = cmd.RunStdString(git.DefaultContext, &git.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
|
||||
|
@ -79,7 +79,7 @@ func RefixMergeBase(x *xorm.Engine) error {
|
||||
|
||||
gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index)
|
||||
|
||||
parentsString, _, err := git.NewCommand(git.DefaultContext, "rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(&git.RunOpts{Dir: repoPath})
|
||||
parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(git.DefaultContext, &git.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
|
||||
@ -92,9 +92,9 @@ func RefixMergeBase(x *xorm.Engine) error {
|
||||
// we should recalculate
|
||||
refs := append([]string{}, parents[1:]...)
|
||||
refs = append(refs, gitRefName)
|
||||
cmd := git.NewCommand(git.DefaultContext, "merge-base").AddDashesAndList(refs...)
|
||||
cmd := git.NewCommand("merge-base").AddDashesAndList(refs...)
|
||||
|
||||
pr.MergeBase, _, err = cmd.RunStdString(&git.RunOpts{Dir: repoPath})
|
||||
pr.MergeBase, _, err = cmd.RunStdString(git.DefaultContext, &git.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
|
||||
|
19
models/migrations/v1_24/v314.go
Normal file
19
models/migrations/v1_24/v314.go
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_24 //nolint
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func UpdateOwnerIDOfRepoLevelActionsTables(x *xorm.Engine) error {
|
||||
if _, err := x.Exec("UPDATE `action_runner` SET `owner_id` = 0 WHERE `repo_id` > 0 AND `owner_id` > 0"); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := x.Exec("UPDATE `action_variable` SET `owner_id` = 0 WHERE `repo_id` > 0 AND `owner_id` > 0"); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := x.Exec("UPDATE `secret` SET `owner_id` = 0 WHERE `repo_id` > 0 AND `owner_id` > 0")
|
||||
return err
|
||||
}
|
@ -320,7 +320,7 @@ func TestAccessibleReposEnv_CountRepos(t *testing.T) {
|
||||
testSuccess := func(userID, expectedCount int64) {
|
||||
env, err := repo_model.AccessibleReposEnv(db.DefaultContext, org, userID)
|
||||
assert.NoError(t, err)
|
||||
count, err := env.CountRepos()
|
||||
count, err := env.CountRepos(db.DefaultContext)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, expectedCount, count)
|
||||
}
|
||||
@ -334,7 +334,7 @@ func TestAccessibleReposEnv_RepoIDs(t *testing.T) {
|
||||
testSuccess := func(userID int64, expectedRepoIDs []int64) {
|
||||
env, err := repo_model.AccessibleReposEnv(db.DefaultContext, org, userID)
|
||||
assert.NoError(t, err)
|
||||
repoIDs, err := env.RepoIDs(1, 100)
|
||||
repoIDs, err := env.RepoIDs(db.DefaultContext, 1, 100)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expectedRepoIDs, repoIDs)
|
||||
}
|
||||
@ -348,7 +348,7 @@ func TestAccessibleReposEnv_Repos(t *testing.T) {
|
||||
testSuccess := func(userID int64, expectedRepoIDs []int64) {
|
||||
env, err := repo_model.AccessibleReposEnv(db.DefaultContext, org, userID)
|
||||
assert.NoError(t, err)
|
||||
repos, err := env.Repos(1, 100)
|
||||
repos, err := env.Repos(db.DefaultContext, 1, 100)
|
||||
assert.NoError(t, err)
|
||||
expectedRepos := make(repo_model.RepositoryList, len(expectedRepoIDs))
|
||||
for i, repoID := range expectedRepoIDs {
|
||||
@ -367,7 +367,7 @@ func TestAccessibleReposEnv_MirrorRepos(t *testing.T) {
|
||||
testSuccess := func(userID int64, expectedRepoIDs []int64) {
|
||||
env, err := repo_model.AccessibleReposEnv(db.DefaultContext, org, userID)
|
||||
assert.NoError(t, err)
|
||||
repos, err := env.MirrorRepos()
|
||||
repos, err := env.MirrorRepos(db.DefaultContext)
|
||||
assert.NoError(t, err)
|
||||
expectedRepos := make(repo_model.RepositoryList, len(expectedRepoIDs))
|
||||
for i, repoID := range expectedRepoIDs {
|
||||
|
@ -133,5 +133,8 @@ func GetTeamsByOrgIDs(ctx context.Context, orgIDs []int64) (TeamList, error) {
|
||||
|
||||
func GetTeamsByIDs(ctx context.Context, teamIDs []int64) (map[int64]*Team, error) {
|
||||
teams := make(map[int64]*Team, len(teamIDs))
|
||||
if len(teamIDs) == 0 {
|
||||
return teams, nil
|
||||
}
|
||||
return teams, db.GetEngine(ctx).Where(builder.In("`id`", teamIDs)).Find(&teams)
|
||||
}
|
||||
|
@ -336,6 +336,9 @@ func UpdateColumnSorting(ctx context.Context, cl ColumnList) error {
|
||||
|
||||
func GetColumnsByIDs(ctx context.Context, projectID int64, columnsIDs []int64) (ColumnList, error) {
|
||||
columns := make([]*Column, 0, 5)
|
||||
if len(columnsIDs) == 0 {
|
||||
return columns, nil
|
||||
}
|
||||
if err := db.GetEngine(ctx).
|
||||
Where("project_id =?", projectID).
|
||||
In("id", columnsIDs).
|
||||
|
@ -50,15 +50,15 @@ func (archiver *RepoArchiver) RelativePath() string {
|
||||
func repoArchiverForRelativePath(relativePath string) (*RepoArchiver, error) {
|
||||
parts := strings.SplitN(relativePath, "/", 3)
|
||||
if len(parts) != 3 {
|
||||
return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument}
|
||||
return nil, util.NewInvalidArgumentErrorf("invalid storage path: must have 3 parts")
|
||||
}
|
||||
repoID, err := strconv.ParseInt(parts[0], 10, 64)
|
||||
if err != nil {
|
||||
return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument}
|
||||
return nil, util.NewInvalidArgumentErrorf("invalid storage path: invalid repo id")
|
||||
}
|
||||
commitID, archiveType := git.SplitArchiveNameType(parts[2])
|
||||
if archiveType == git.ArchiveUnknown {
|
||||
return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument}
|
||||
return nil, util.NewInvalidArgumentErrorf("invalid storage path: invalid archive type")
|
||||
}
|
||||
return &RepoArchiver{RepoID: repoID, CommitID: commitID, Type: archiveType}, nil
|
||||
}
|
||||
|
@ -47,10 +47,10 @@ func GetTeamRepositories(ctx context.Context, opts *SearchTeamRepoOptions) (Repo
|
||||
// AccessibleReposEnvironment operations involving the repositories that are
|
||||
// accessible to a particular user
|
||||
type AccessibleReposEnvironment interface {
|
||||
CountRepos() (int64, error)
|
||||
RepoIDs(page, pageSize int) ([]int64, error)
|
||||
Repos(page, pageSize int) (RepositoryList, error)
|
||||
MirrorRepos() (RepositoryList, error)
|
||||
CountRepos(ctx context.Context) (int64, error)
|
||||
RepoIDs(ctx context.Context, page, pageSize int) ([]int64, error)
|
||||
Repos(ctx context.Context, page, pageSize int) (RepositoryList, error)
|
||||
MirrorRepos(ctx context.Context) (RepositoryList, error)
|
||||
AddKeyword(keyword string)
|
||||
SetSort(db.SearchOrderBy)
|
||||
}
|
||||
@ -60,7 +60,6 @@ type accessibleReposEnv struct {
|
||||
user *user_model.User
|
||||
team *org_model.Team
|
||||
teamIDs []int64
|
||||
ctx context.Context
|
||||
keyword string
|
||||
orderBy db.SearchOrderBy
|
||||
}
|
||||
@ -86,18 +85,16 @@ func AccessibleReposEnv(ctx context.Context, org *org_model.Organization, userID
|
||||
org: org,
|
||||
user: user,
|
||||
teamIDs: teamIDs,
|
||||
ctx: ctx,
|
||||
orderBy: db.SearchOrderByRecentUpdated,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// AccessibleTeamReposEnv an AccessibleReposEnvironment for the repositories in `org`
|
||||
// that are accessible to the specified team.
|
||||
func AccessibleTeamReposEnv(ctx context.Context, org *org_model.Organization, team *org_model.Team) AccessibleReposEnvironment {
|
||||
func AccessibleTeamReposEnv(org *org_model.Organization, team *org_model.Team) AccessibleReposEnvironment {
|
||||
return &accessibleReposEnv{
|
||||
org: org,
|
||||
team: team,
|
||||
ctx: ctx,
|
||||
orderBy: db.SearchOrderByRecentUpdated,
|
||||
}
|
||||
}
|
||||
@ -123,8 +120,8 @@ func (env *accessibleReposEnv) cond() builder.Cond {
|
||||
return cond
|
||||
}
|
||||
|
||||
func (env *accessibleReposEnv) CountRepos() (int64, error) {
|
||||
repoCount, err := db.GetEngine(env.ctx).
|
||||
func (env *accessibleReposEnv) CountRepos(ctx context.Context) (int64, error) {
|
||||
repoCount, err := db.GetEngine(ctx).
|
||||
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
|
||||
Where(env.cond()).
|
||||
Distinct("`repository`.id").
|
||||
@ -135,13 +132,13 @@ func (env *accessibleReposEnv) CountRepos() (int64, error) {
|
||||
return repoCount, nil
|
||||
}
|
||||
|
||||
func (env *accessibleReposEnv) RepoIDs(page, pageSize int) ([]int64, error) {
|
||||
func (env *accessibleReposEnv) RepoIDs(ctx context.Context, page, pageSize int) ([]int64, error) {
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
repoIDs := make([]int64, 0, pageSize)
|
||||
return repoIDs, db.GetEngine(env.ctx).
|
||||
return repoIDs, db.GetEngine(ctx).
|
||||
Table("repository").
|
||||
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
|
||||
Where(env.cond()).
|
||||
@ -152,8 +149,8 @@ func (env *accessibleReposEnv) RepoIDs(page, pageSize int) ([]int64, error) {
|
||||
Find(&repoIDs)
|
||||
}
|
||||
|
||||
func (env *accessibleReposEnv) Repos(page, pageSize int) (RepositoryList, error) {
|
||||
repoIDs, err := env.RepoIDs(page, pageSize)
|
||||
func (env *accessibleReposEnv) Repos(ctx context.Context, page, pageSize int) (RepositoryList, error) {
|
||||
repoIDs, err := env.RepoIDs(ctx, page, pageSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetUserRepositoryIDs: %w", err)
|
||||
}
|
||||
@ -163,15 +160,15 @@ func (env *accessibleReposEnv) Repos(page, pageSize int) (RepositoryList, error)
|
||||
return repos, nil
|
||||
}
|
||||
|
||||
return repos, db.GetEngine(env.ctx).
|
||||
return repos, db.GetEngine(ctx).
|
||||
In("`repository`.id", repoIDs).
|
||||
OrderBy(string(env.orderBy)).
|
||||
Find(&repos)
|
||||
}
|
||||
|
||||
func (env *accessibleReposEnv) MirrorRepoIDs() ([]int64, error) {
|
||||
func (env *accessibleReposEnv) MirrorRepoIDs(ctx context.Context) ([]int64, error) {
|
||||
repoIDs := make([]int64, 0, 10)
|
||||
return repoIDs, db.GetEngine(env.ctx).
|
||||
return repoIDs, db.GetEngine(ctx).
|
||||
Table("repository").
|
||||
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id AND `repository`.is_mirror=?", true).
|
||||
Where(env.cond()).
|
||||
@ -181,8 +178,8 @@ func (env *accessibleReposEnv) MirrorRepoIDs() ([]int64, error) {
|
||||
Find(&repoIDs)
|
||||
}
|
||||
|
||||
func (env *accessibleReposEnv) MirrorRepos() (RepositoryList, error) {
|
||||
repoIDs, err := env.MirrorRepoIDs()
|
||||
func (env *accessibleReposEnv) MirrorRepos(ctx context.Context) (RepositoryList, error) {
|
||||
repoIDs, err := env.MirrorRepoIDs(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("MirrorRepoIDs: %w", err)
|
||||
}
|
||||
@ -192,7 +189,7 @@ func (env *accessibleReposEnv) MirrorRepos() (RepositoryList, error) {
|
||||
return repos, nil
|
||||
}
|
||||
|
||||
return repos, db.GetEngine(env.ctx).
|
||||
return repos, db.GetEngine(ctx).
|
||||
In("`repository`.id", repoIDs).
|
||||
Find(&repos)
|
||||
}
|
||||
|
@ -839,6 +839,9 @@ func GetRepositoryByID(ctx context.Context, id int64) (*Repository, error) {
|
||||
// GetRepositoriesMapByIDs returns the repositories by given id slice.
|
||||
func GetRepositoriesMapByIDs(ctx context.Context, ids []int64) (map[int64]*Repository, error) {
|
||||
repos := make(map[int64]*Repository, len(ids))
|
||||
if len(ids) == 0 {
|
||||
return repos, nil
|
||||
}
|
||||
return repos, db.GetEngine(ctx).In("id", ids).Find(&repos)
|
||||
}
|
||||
|
||||
|
@ -21,11 +21,6 @@ import (
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
// FindReposMapByIDs find repos as map
|
||||
func FindReposMapByIDs(ctx context.Context, repoIDs []int64, res map[int64]*Repository) error {
|
||||
return db.GetEngine(ctx).In("id", repoIDs).Find(&res)
|
||||
}
|
||||
|
||||
// RepositoryListDefaultPageSize is the default number of repositories
|
||||
// to load in memory when running administrative tasks on all (or almost
|
||||
// all) of them.
|
||||
|
@ -165,3 +165,17 @@ func GetSecretsOfTask(ctx context.Context, task *actions_model.ActionTask) (map[
|
||||
|
||||
return secrets, nil
|
||||
}
|
||||
|
||||
func CountWrongRepoLevelSecrets(ctx context.Context) (int64, error) {
|
||||
var result int64
|
||||
_, err := db.GetEngine(ctx).SQL("SELECT count(`id`) FROM `secret` WHERE `repo_id` > 0 AND `owner_id` > 0").Get(&result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func UpdateWrongRepoLevelSecrets(ctx context.Context) (int64, error) {
|
||||
result, err := db.GetEngine(ctx).Exec("UPDATE `secret` SET `owner_id` = 0 WHERE `repo_id` > 0 AND `owner_id` > 0")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected()
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ func SetMustChangePassword(ctx context.Context, all, mustChangePassword bool, in
|
||||
if !all {
|
||||
include = sliceTrimSpaceDropEmpty(include)
|
||||
if len(include) == 0 {
|
||||
return 0, util.NewSilentWrapErrorf(util.ErrInvalidArgument, "no users to include provided")
|
||||
return 0, util.ErrorWrap(util.ErrInvalidArgument, "no users to include provided")
|
||||
}
|
||||
|
||||
cond = cond.And(builder.In("lower_name", include))
|
||||
|
@ -11,6 +11,10 @@ import (
|
||||
|
||||
func GetUsersMapByIDs(ctx context.Context, userIDs []int64) (map[int64]*User, error) {
|
||||
userMaps := make(map[int64]*User, len(userIDs))
|
||||
if len(userIDs) == 0 {
|
||||
return userMaps, nil
|
||||
}
|
||||
|
||||
left := len(userIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
|
@ -73,7 +73,7 @@ func TestWebhook_EventsArray(t *testing.T) {
|
||||
"pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone",
|
||||
"pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected",
|
||||
"pull_request_review_comment", "pull_request_sync", "pull_request_review_request", "wiki", "repository", "release",
|
||||
"package", "status",
|
||||
"package", "status", "workflow_job",
|
||||
},
|
||||
(&Webhook{
|
||||
HookEvent: &webhook_module.HookEvent{SendEverything: true},
|
||||
|
@ -17,7 +17,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
@ -139,24 +138,3 @@ func Int64sToStrings(ints []int64) []string {
|
||||
}
|
||||
return strs
|
||||
}
|
||||
|
||||
// EntryIcon returns the octicon name for displaying files/directories
|
||||
func EntryIcon(entry *git.TreeEntry) string {
|
||||
switch {
|
||||
case entry.IsLink():
|
||||
te, err := entry.FollowLink()
|
||||
if err != nil {
|
||||
return "file-symlink-file"
|
||||
}
|
||||
if te.IsDir() {
|
||||
return "file-directory-symlink"
|
||||
}
|
||||
return "file-symlink-file"
|
||||
case entry.IsDir():
|
||||
return "file-directory-fill"
|
||||
case entry.IsSubModule():
|
||||
return "file-submodule"
|
||||
}
|
||||
|
||||
return "file"
|
||||
}
|
||||
|
27
modules/fileicon/basic.go
Normal file
27
modules/fileicon/basic.go
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package fileicon
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/svg"
|
||||
)
|
||||
|
||||
func BasicThemeIcon(entry *git.TreeEntry) template.HTML {
|
||||
svgName := "octicon-file"
|
||||
switch {
|
||||
case entry.IsLink():
|
||||
svgName = "octicon-file-symlink-file"
|
||||
if te, err := entry.FollowLink(); err == nil && te.IsDir() {
|
||||
svgName = "octicon-file-directory-symlink"
|
||||
}
|
||||
case entry.IsDir():
|
||||
svgName = "octicon-file-directory-fill"
|
||||
case entry.IsSubModule():
|
||||
svgName = "octicon-file-submodule"
|
||||
}
|
||||
return svg.RenderHTML(svgName)
|
||||
}
|
157
modules/fileicon/material.go
Normal file
157
modules/fileicon/material.go
Normal file
@ -0,0 +1,157 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package fileicon
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/options"
|
||||
"code.gitea.io/gitea/modules/reqctx"
|
||||
"code.gitea.io/gitea/modules/svg"
|
||||
)
|
||||
|
||||
type materialIconRulesData struct {
|
||||
FileNames map[string]string `json:"fileNames"`
|
||||
FolderNames map[string]string `json:"folderNames"`
|
||||
FileExtensions map[string]string `json:"fileExtensions"`
|
||||
LanguageIDs map[string]string `json:"languageIds"`
|
||||
}
|
||||
|
||||
type MaterialIconProvider struct {
|
||||
once sync.Once
|
||||
rules *materialIconRulesData
|
||||
svgs map[string]string
|
||||
}
|
||||
|
||||
var materialIconProvider MaterialIconProvider
|
||||
|
||||
func DefaultMaterialIconProvider() *MaterialIconProvider {
|
||||
materialIconProvider.once.Do(materialIconProvider.loadData)
|
||||
return &materialIconProvider
|
||||
}
|
||||
|
||||
func (m *MaterialIconProvider) loadData() {
|
||||
buf, err := options.AssetFS().ReadFile("fileicon/material-icon-rules.json")
|
||||
if err != nil {
|
||||
log.Error("Failed to read material icon rules: %v", err)
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(buf, &m.rules)
|
||||
if err != nil {
|
||||
log.Error("Failed to unmarshal material icon rules: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
buf, err = options.AssetFS().ReadFile("fileicon/material-icon-svgs.json")
|
||||
if err != nil {
|
||||
log.Error("Failed to read material icon rules: %v", err)
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(buf, &m.svgs)
|
||||
if err != nil {
|
||||
log.Error("Failed to unmarshal material icon rules: %v", err)
|
||||
return
|
||||
}
|
||||
log.Debug("Loaded material icon rules and SVG images")
|
||||
}
|
||||
|
||||
func (m *MaterialIconProvider) renderFileIconSVG(ctx reqctx.RequestContext, name, svg string) template.HTML {
|
||||
data := ctx.GetData()
|
||||
renderedSVGs, _ := data["_RenderedSVGs"].(map[string]bool)
|
||||
if renderedSVGs == nil {
|
||||
renderedSVGs = make(map[string]bool)
|
||||
data["_RenderedSVGs"] = renderedSVGs
|
||||
}
|
||||
// This part is a bit hacky, but it works really well. It should be safe to do so because all SVG icons are generated by us.
|
||||
// Will try to refactor this in the future.
|
||||
if !strings.HasPrefix(svg, "<svg") {
|
||||
panic("Invalid SVG icon")
|
||||
}
|
||||
svgID := "svg-mfi-" + name
|
||||
svgCommonAttrs := `class="svg fileicon" width="16" height="16" aria-hidden="true"`
|
||||
posOuterBefore := strings.IndexByte(svg, '>')
|
||||
if renderedSVGs[svgID] && posOuterBefore != -1 {
|
||||
return template.HTML(`<svg ` + svgCommonAttrs + `><use xlink:href="#` + svgID + `"></use></svg>`)
|
||||
}
|
||||
svg = `<svg id="` + svgID + `" ` + svgCommonAttrs + svg[4:]
|
||||
renderedSVGs[svgID] = true
|
||||
return template.HTML(svg)
|
||||
}
|
||||
|
||||
func (m *MaterialIconProvider) FileIcon(ctx reqctx.RequestContext, entry *git.TreeEntry) template.HTML {
|
||||
if m.rules == nil {
|
||||
return BasicThemeIcon(entry)
|
||||
}
|
||||
|
||||
if entry.IsLink() {
|
||||
if te, err := entry.FollowLink(); err == nil && te.IsDir() {
|
||||
return svg.RenderHTML("material-folder-symlink")
|
||||
}
|
||||
return svg.RenderHTML("octicon-file-symlink-file") // TODO: find some better icons for them
|
||||
}
|
||||
|
||||
name := m.findIconNameByGit(entry)
|
||||
if name == "folder" {
|
||||
// the material icon pack's "folder" icon doesn't look good, so use our built-in one
|
||||
return svg.RenderHTML("material-folder-generic")
|
||||
}
|
||||
if iconSVG, ok := m.svgs[name]; ok && iconSVG != "" {
|
||||
return m.renderFileIconSVG(ctx, name, iconSVG)
|
||||
}
|
||||
return svg.RenderHTML("octicon-file")
|
||||
}
|
||||
|
||||
func (m *MaterialIconProvider) findIconNameWithLangID(s string) string {
|
||||
if _, ok := m.svgs[s]; ok {
|
||||
return s
|
||||
}
|
||||
if s, ok := m.rules.LanguageIDs[s]; ok {
|
||||
if _, ok = m.svgs[s]; ok {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *MaterialIconProvider) FindIconName(name string, isDir bool) string {
|
||||
fileNameLower := strings.ToLower(path.Base(name))
|
||||
if isDir {
|
||||
if s, ok := m.rules.FolderNames[fileNameLower]; ok {
|
||||
return s
|
||||
}
|
||||
return "folder"
|
||||
}
|
||||
|
||||
if s, ok := m.rules.FileNames[fileNameLower]; ok {
|
||||
if s = m.findIconNameWithLangID(s); s != "" {
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
for i := len(fileNameLower) - 1; i >= 0; i-- {
|
||||
if fileNameLower[i] == '.' {
|
||||
ext := fileNameLower[i+1:]
|
||||
if s, ok := m.rules.FileExtensions[ext]; ok {
|
||||
if s = m.findIconNameWithLangID(s); s != "" {
|
||||
return s
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "file"
|
||||
}
|
||||
|
||||
func (m *MaterialIconProvider) findIconNameByGit(entry *git.TreeEntry) string {
|
||||
if entry.IsSubModule() {
|
||||
return "folder-git"
|
||||
}
|
||||
return m.FindIconName(entry.Name(), entry.IsDir())
|
||||
}
|
26
modules/fileicon/material_test.go
Normal file
26
modules/fileicon/material_test.go
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package fileicon_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/modules/fileicon"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{FixtureFiles: []string{}})
|
||||
}
|
||||
|
||||
func TestFindIconName(t *testing.T) {
|
||||
unittest.PrepareTestEnv(t)
|
||||
p := fileicon.DefaultMaterialIconProvider()
|
||||
assert.Equal(t, "php", p.FindIconName("foo.php", false))
|
||||
assert.Equal(t, "php", p.FindIconName("foo.PHP", false))
|
||||
assert.Equal(t, "javascript", p.FindIconName("foo.js", false))
|
||||
assert.Equal(t, "visualstudio", p.FindIconName("foo.vba", false))
|
||||
}
|
@ -29,8 +29,8 @@ 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(ctx, "rev-parse").
|
||||
Run(&RunOpts{
|
||||
err := NewCommand("rev-parse").
|
||||
Run(ctx, &RunOpts{
|
||||
Dir: repoPath,
|
||||
Stderr: &stderr,
|
||||
})
|
||||
@ -61,8 +61,8 @@ func catFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError,
|
||||
|
||||
go func() {
|
||||
stderr := strings.Builder{}
|
||||
err := NewCommand(ctx, "cat-file", "--batch-check").
|
||||
Run(&RunOpts{
|
||||
err := NewCommand("cat-file", "--batch-check").
|
||||
Run(ctx, &RunOpts{
|
||||
Dir: repoPath,
|
||||
Stdin: batchStdinReader,
|
||||
Stdout: batchStdoutWriter,
|
||||
@ -109,8 +109,8 @@ func catFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufi
|
||||
|
||||
go func() {
|
||||
stderr := strings.Builder{}
|
||||
err := NewCommand(ctx, "cat-file", "--batch").
|
||||
Run(&RunOpts{
|
||||
err := NewCommand("cat-file", "--batch").
|
||||
Run(ctx, &RunOpts{
|
||||
Dir: repoPath,
|
||||
Stdin: batchStdinReader,
|
||||
Stdout: batchStdoutWriter,
|
||||
|
@ -135,7 +135,7 @@ func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath
|
||||
ignoreRevsFile = tryCreateBlameIgnoreRevsFile(commit)
|
||||
}
|
||||
|
||||
cmd := NewCommandContextNoGlobals(ctx, "blame", "--porcelain")
|
||||
cmd := NewCommandNoGlobals("blame", "--porcelain")
|
||||
if ignoreRevsFile != nil {
|
||||
// Possible improvement: use --ignore-revs-file /dev/stdin on unix
|
||||
// There is no equivalent on Windows. May be implemented if Gitea uses an external git backend.
|
||||
@ -155,7 +155,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(&RunOpts{
|
||||
err := cmd.Run(ctx, &RunOpts{
|
||||
UseContextTimeout: true,
|
||||
Dir: repoPath,
|
||||
Stdout: stdout,
|
||||
|
@ -7,6 +7,7 @@ package git
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"code.gitea.io/gitea/modules/typesniffer"
|
||||
@ -34,8 +35,9 @@ func (b *Blob) GetBlobContent(limit int64) (string, error) {
|
||||
return string(buf), err
|
||||
}
|
||||
|
||||
// GetBlobLineCount gets line count of the blob
|
||||
func (b *Blob) GetBlobLineCount() (int, error) {
|
||||
// GetBlobLineCount gets line count of the blob.
|
||||
// It will also try to write the content to w if it's not nil, then we could pre-fetch the content without reading it again.
|
||||
func (b *Blob) GetBlobLineCount(w io.Writer) (int, error) {
|
||||
reader, err := b.DataAsync()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@ -44,20 +46,20 @@ func (b *Blob) GetBlobLineCount() (int, error) {
|
||||
buf := make([]byte, 32*1024)
|
||||
count := 1
|
||||
lineSep := []byte{'\n'}
|
||||
|
||||
c, err := reader.Read(buf)
|
||||
if c == 0 && err == io.EOF {
|
||||
return 0, nil
|
||||
}
|
||||
for {
|
||||
c, err := reader.Read(buf)
|
||||
if w != nil {
|
||||
if _, err := w.Write(buf[:c]); err != nil {
|
||||
return count, err
|
||||
}
|
||||
}
|
||||
count += bytes.Count(buf[:c], lineSep)
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
case errors.Is(err, io.EOF):
|
||||
return count, nil
|
||||
case err != nil:
|
||||
return count, err
|
||||
}
|
||||
c, err = reader.Read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,6 @@ const DefaultLocale = "C"
|
||||
type Command struct {
|
||||
prog string
|
||||
args []string
|
||||
parentContext context.Context
|
||||
globalArgsLength int
|
||||
brokenArgs []string
|
||||
}
|
||||
@ -82,7 +81,7 @@ func (c *Command) LogString() string {
|
||||
|
||||
// NewCommand creates and returns a new Git Command based on given command and arguments.
|
||||
// Each argument should be safe to be trusted. User-provided arguments should be passed to AddDynamicArguments instead.
|
||||
func NewCommand(ctx context.Context, args ...internal.CmdArg) *Command {
|
||||
func NewCommand(args ...internal.CmdArg) *Command {
|
||||
// Make an explicit copy of globalCommandArgs, otherwise append might overwrite it
|
||||
cargs := make([]string, 0, len(globalCommandArgs)+len(args))
|
||||
for _, arg := range globalCommandArgs {
|
||||
@ -94,31 +93,23 @@ func NewCommand(ctx context.Context, args ...internal.CmdArg) *Command {
|
||||
return &Command{
|
||||
prog: GitExecutable,
|
||||
args: cargs,
|
||||
parentContext: ctx,
|
||||
globalArgsLength: len(globalCommandArgs),
|
||||
}
|
||||
}
|
||||
|
||||
// NewCommandContextNoGlobals creates and returns a new Git Command based on given command and arguments only with the specify args and don't care global command args
|
||||
// NewCommandNoGlobals creates and returns a new Git Command based on given command and arguments only with the specified args and don't use global command args
|
||||
// Each argument should be safe to be trusted. User-provided arguments should be passed to AddDynamicArguments instead.
|
||||
func NewCommandContextNoGlobals(ctx context.Context, args ...internal.CmdArg) *Command {
|
||||
func NewCommandNoGlobals(args ...internal.CmdArg) *Command {
|
||||
cargs := make([]string, 0, len(args))
|
||||
for _, arg := range args {
|
||||
cargs = append(cargs, string(arg))
|
||||
}
|
||||
return &Command{
|
||||
prog: GitExecutable,
|
||||
args: cargs,
|
||||
parentContext: ctx,
|
||||
prog: GitExecutable,
|
||||
args: cargs,
|
||||
}
|
||||
}
|
||||
|
||||
// SetParentContext sets the parent context for this command
|
||||
func (c *Command) SetParentContext(ctx context.Context) *Command {
|
||||
c.parentContext = ctx
|
||||
return c
|
||||
}
|
||||
|
||||
// isSafeArgumentValue checks if the argument is safe to be used as a value (not an option)
|
||||
func isSafeArgumentValue(s string) bool {
|
||||
return s == "" || s[0] != '-'
|
||||
@ -277,11 +268,11 @@ func CommonCmdServEnvs() []string {
|
||||
var ErrBrokenCommand = errors.New("git command is broken")
|
||||
|
||||
// Run runs the command with the RunOpts
|
||||
func (c *Command) Run(opts *RunOpts) error {
|
||||
return c.run(1, opts)
|
||||
func (c *Command) Run(ctx context.Context, opts *RunOpts) error {
|
||||
return c.run(ctx, 1, opts)
|
||||
}
|
||||
|
||||
func (c *Command) run(skip int, opts *RunOpts) error {
|
||||
func (c *Command) run(ctx context.Context, skip int, opts *RunOpts) error {
|
||||
if len(c.brokenArgs) != 0 {
|
||||
log.Error("git command is broken: %s, broken args: %s", c.LogString(), strings.Join(c.brokenArgs, " "))
|
||||
return ErrBrokenCommand
|
||||
@ -305,19 +296,18 @@ func (c *Command) run(skip int, opts *RunOpts) error {
|
||||
desc := fmt.Sprintf("git.Run(by:%s, repo:%s): %s", callerInfo, logArgSanitize(opts.Dir), cmdLogString)
|
||||
log.Debug("git.Command: %s", desc)
|
||||
|
||||
_, span := gtprof.GetTracer().Start(c.parentContext, gtprof.TraceSpanGitRun)
|
||||
_, span := gtprof.GetTracer().Start(ctx, gtprof.TraceSpanGitRun)
|
||||
defer span.End()
|
||||
span.SetAttributeString(gtprof.TraceAttrFuncCaller, callerInfo)
|
||||
span.SetAttributeString(gtprof.TraceAttrGitCommand, cmdLogString)
|
||||
|
||||
var ctx context.Context
|
||||
var cancel context.CancelFunc
|
||||
var finished context.CancelFunc
|
||||
|
||||
if opts.UseContextTimeout {
|
||||
ctx, cancel, finished = process.GetManager().AddContext(c.parentContext, desc)
|
||||
ctx, cancel, finished = process.GetManager().AddContext(ctx, desc)
|
||||
} else {
|
||||
ctx, cancel, finished = process.GetManager().AddContextTimeout(c.parentContext, timeout, desc)
|
||||
ctx, cancel, finished = process.GetManager().AddContextTimeout(ctx, timeout, desc)
|
||||
}
|
||||
defer finished()
|
||||
|
||||
@ -410,8 +400,8 @@ func IsErrorExitCode(err error, code int) bool {
|
||||
}
|
||||
|
||||
// RunStdString runs the command with options and returns stdout/stderr as string. and store stderr to returned error (err combined with stderr).
|
||||
func (c *Command) RunStdString(opts *RunOpts) (stdout, stderr string, runErr RunStdError) {
|
||||
stdoutBytes, stderrBytes, err := c.runStdBytes(opts)
|
||||
func (c *Command) RunStdString(ctx context.Context, opts *RunOpts) (stdout, stderr string, runErr RunStdError) {
|
||||
stdoutBytes, stderrBytes, err := c.runStdBytes(ctx, opts)
|
||||
stdout = util.UnsafeBytesToString(stdoutBytes)
|
||||
stderr = util.UnsafeBytesToString(stderrBytes)
|
||||
if err != nil {
|
||||
@ -422,11 +412,11 @@ func (c *Command) RunStdString(opts *RunOpts) (stdout, stderr string, runErr Run
|
||||
}
|
||||
|
||||
// RunStdBytes runs the command with options and returns stdout/stderr as bytes. and store stderr to returned error (err combined with stderr).
|
||||
func (c *Command) RunStdBytes(opts *RunOpts) (stdout, stderr []byte, runErr RunStdError) {
|
||||
return c.runStdBytes(opts)
|
||||
func (c *Command) RunStdBytes(ctx context.Context, opts *RunOpts) (stdout, stderr []byte, runErr RunStdError) {
|
||||
return c.runStdBytes(ctx, opts)
|
||||
}
|
||||
|
||||
func (c *Command) runStdBytes(opts *RunOpts) (stdout, stderr []byte, runErr RunStdError) {
|
||||
func (c *Command) runStdBytes(ctx context.Context, opts *RunOpts) (stdout, stderr []byte, runErr RunStdError) {
|
||||
if opts == nil {
|
||||
opts = &RunOpts{}
|
||||
}
|
||||
@ -449,7 +439,7 @@ func (c *Command) runStdBytes(opts *RunOpts) (stdout, stderr []byte, runErr RunS
|
||||
PipelineFunc: opts.PipelineFunc,
|
||||
}
|
||||
|
||||
err := c.run(2, newOpts)
|
||||
err := c.run(ctx, 2, newOpts)
|
||||
stderr = stderrBuf.Bytes()
|
||||
if err != nil {
|
||||
return nil, stderr, &runStdError{err: err, stderr: util.UnsafeBytesToString(stderr)}
|
||||
|
@ -15,9 +15,9 @@ func TestRunWithContextNoTimeout(t *testing.T) {
|
||||
maxLoops := 10
|
||||
|
||||
// 'git --version' does not block so it must be finished before the timeout triggered.
|
||||
cmd := NewCommand(t.Context(), "--version")
|
||||
cmd := NewCommand("--version")
|
||||
for i := 0; i < maxLoops; i++ {
|
||||
if err := cmd.Run(&RunOpts{}); err != nil {
|
||||
if err := cmd.Run(t.Context(), &RunOpts{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@ -27,9 +27,9 @@ func TestRunWithContextTimeout(t *testing.T) {
|
||||
maxLoops := 10
|
||||
|
||||
// 'git hash-object --stdin' blocks on stdin so we can have the timeout triggered.
|
||||
cmd := NewCommand(t.Context(), "hash-object", "--stdin")
|
||||
cmd := NewCommand("hash-object", "--stdin")
|
||||
for i := 0; i < maxLoops; i++ {
|
||||
if err := cmd.Run(&RunOpts{Timeout: 1 * time.Millisecond}); err != nil {
|
||||
if err := cmd.Run(t.Context(), &RunOpts{Timeout: 1 * time.Millisecond}); err != nil {
|
||||
if err != context.DeadlineExceeded {
|
||||
t.Fatalf("Testing %d/%d: %v", i, maxLoops, err)
|
||||
}
|
||||
|
@ -10,14 +10,14 @@ import (
|
||||
)
|
||||
|
||||
func TestRunWithContextStd(t *testing.T) {
|
||||
cmd := NewCommand(t.Context(), "--version")
|
||||
stdout, stderr, err := cmd.RunStdString(&RunOpts{})
|
||||
cmd := NewCommand("--version")
|
||||
stdout, stderr, err := cmd.RunStdString(t.Context(), &RunOpts{})
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, stderr)
|
||||
assert.Contains(t, stdout, "git version")
|
||||
|
||||
cmd = NewCommand(t.Context(), "--no-such-arg")
|
||||
stdout, stderr, err = cmd.RunStdString(&RunOpts{})
|
||||
cmd = NewCommand("--no-such-arg")
|
||||
stdout, stderr, err = cmd.RunStdString(t.Context(), &RunOpts{})
|
||||
if assert.Error(t, err) {
|
||||
assert.Equal(t, stderr, err.Stderr())
|
||||
assert.Contains(t, err.Stderr(), "unknown option:")
|
||||
@ -25,17 +25,17 @@ func TestRunWithContextStd(t *testing.T) {
|
||||
assert.Empty(t, stdout)
|
||||
}
|
||||
|
||||
cmd = NewCommand(t.Context())
|
||||
cmd = NewCommand()
|
||||
cmd.AddDynamicArguments("-test")
|
||||
assert.ErrorIs(t, cmd.Run(&RunOpts{}), ErrBrokenCommand)
|
||||
assert.ErrorIs(t, cmd.Run(t.Context(), &RunOpts{}), ErrBrokenCommand)
|
||||
|
||||
cmd = NewCommand(t.Context())
|
||||
cmd = NewCommand()
|
||||
cmd.AddDynamicArguments("--test")
|
||||
assert.ErrorIs(t, cmd.Run(&RunOpts{}), ErrBrokenCommand)
|
||||
assert.ErrorIs(t, cmd.Run(t.Context(), &RunOpts{}), ErrBrokenCommand)
|
||||
|
||||
subCmd := "version"
|
||||
cmd = NewCommand(t.Context()).AddDynamicArguments(subCmd) // for test purpose only, the sub-command should never be dynamic for production
|
||||
stdout, stderr, err = cmd.RunStdString(&RunOpts{})
|
||||
cmd = NewCommand().AddDynamicArguments(subCmd) // for test purpose only, the sub-command should never be dynamic for production
|
||||
stdout, stderr, err = cmd.RunStdString(t.Context(), &RunOpts{})
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, stderr)
|
||||
assert.Contains(t, stdout, "git version")
|
||||
@ -53,9 +53,9 @@ func TestGitArgument(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCommandString(t *testing.T) {
|
||||
cmd := NewCommandContextNoGlobals(t.Context(), "a", "-m msg", "it's a test", `say "hello"`)
|
||||
cmd := NewCommandNoGlobals("a", "-m msg", "it's a test", `say "hello"`)
|
||||
assert.EqualValues(t, cmd.prog+` a "-m msg" "it's a test" "say \"hello\""`, cmd.LogString())
|
||||
|
||||
cmd = NewCommandContextNoGlobals(t.Context(), "url: https://a:b@c/", "/root/dir-a/dir-b")
|
||||
cmd = NewCommandNoGlobals("url: https://a:b@c/", "/root/dir-a/dir-b")
|
||||
assert.EqualValues(t, cmd.prog+` "url: https://sanitized-credential@c/" .../dir-a/dir-b`, cmd.LogString())
|
||||
}
|
||||
|
@ -91,12 +91,12 @@ func AddChanges(repoPath string, all bool, files ...string) error {
|
||||
|
||||
// AddChangesWithArgs marks local changes to be ready for commit.
|
||||
func AddChangesWithArgs(repoPath string, globalArgs TrustedCmdArgs, all bool, files ...string) error {
|
||||
cmd := NewCommandContextNoGlobals(DefaultContext, globalArgs...).AddArguments("add")
|
||||
cmd := NewCommandNoGlobals(globalArgs...).AddArguments("add")
|
||||
if all {
|
||||
cmd.AddArguments("--all")
|
||||
}
|
||||
cmd.AddDashesAndList(files...)
|
||||
_, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
|
||||
_, _, err := cmd.RunStdString(DefaultContext, &RunOpts{Dir: repoPath})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -118,7 +118,7 @@ func CommitChanges(repoPath string, opts CommitChangesOptions) error {
|
||||
// CommitChangesWithArgs commits local changes with given committer, author and message.
|
||||
// If author is nil, it will be the same as committer.
|
||||
func CommitChangesWithArgs(repoPath string, args TrustedCmdArgs, opts CommitChangesOptions) error {
|
||||
cmd := NewCommandContextNoGlobals(DefaultContext, args...)
|
||||
cmd := NewCommandNoGlobals(args...)
|
||||
if opts.Committer != nil {
|
||||
cmd.AddOptionValues("-c", "user.name="+opts.Committer.Name)
|
||||
cmd.AddOptionValues("-c", "user.email="+opts.Committer.Email)
|
||||
@ -133,7 +133,7 @@ func CommitChangesWithArgs(repoPath string, args TrustedCmdArgs, opts CommitChan
|
||||
}
|
||||
cmd.AddOptionFormat("--message=%s", opts.Message)
|
||||
|
||||
_, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
|
||||
_, _, err := cmd.RunStdString(DefaultContext, &RunOpts{Dir: repoPath})
|
||||
// No stderr but exit status 1 means nothing to commit.
|
||||
if err != nil && err.Error() == "exit status 1" {
|
||||
return nil
|
||||
@ -143,7 +143,7 @@ func CommitChangesWithArgs(repoPath string, args TrustedCmdArgs, opts CommitChan
|
||||
|
||||
// AllCommitsCount returns count of all commits in repository
|
||||
func AllCommitsCount(ctx context.Context, repoPath string, hidePRRefs bool, files ...string) (int64, error) {
|
||||
cmd := NewCommand(ctx, "rev-list")
|
||||
cmd := NewCommand("rev-list")
|
||||
if hidePRRefs {
|
||||
cmd.AddArguments("--exclude=" + PullPrefix + "*")
|
||||
}
|
||||
@ -152,7 +152,7 @@ func AllCommitsCount(ctx context.Context, repoPath string, hidePRRefs bool, file
|
||||
cmd.AddDashesAndList(files...)
|
||||
}
|
||||
|
||||
stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
|
||||
stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -170,7 +170,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(ctx, "rev-list", "--count")
|
||||
cmd := NewCommand("rev-list", "--count")
|
||||
|
||||
cmd.AddDynamicArguments(opts.Revision...)
|
||||
|
||||
@ -182,7 +182,7 @@ func CommitsCount(ctx context.Context, opts CommitsCountOptions) (int64, error)
|
||||
cmd.AddDashesAndList(opts.RelPath...)
|
||||
}
|
||||
|
||||
stdout, _, err := cmd.RunStdString(&RunOpts{Dir: opts.RepoPath})
|
||||
stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: opts.RepoPath})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -217,7 +217,7 @@ func (c *Commit) HasPreviousCommit(objectID ObjectID) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
_, _, err := NewCommand(c.repo.Ctx, "merge-base", "--is-ancestor").AddDynamicArguments(that, this).RunStdString(&RunOpts{Dir: c.repo.Path})
|
||||
_, _, err := NewCommand("merge-base", "--is-ancestor").AddDynamicArguments(that, this).RunStdString(c.repo.Ctx, &RunOpts{Dir: c.repo.Path})
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
@ -358,12 +358,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(c.repo.Ctx, "name-rev")
|
||||
cmd := 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(&RunOpts{Dir: c.repo.Path})
|
||||
data, _, err := cmd.RunStdString(c.repo.Ctx, &RunOpts{Dir: c.repo.Path})
|
||||
if err != nil {
|
||||
// handle special case where git can not describe commit
|
||||
if strings.Contains(err.Error(), "cannot describe") {
|
||||
@ -441,7 +441,7 @@ func GetCommitFileStatus(ctx context.Context, repoPath, commitID string) (*Commi
|
||||
}()
|
||||
|
||||
stderr := new(bytes.Buffer)
|
||||
err := NewCommand(ctx, "log", "--name-status", "-m", "--pretty=format:", "--first-parent", "--no-renames", "-z", "-1").AddDynamicArguments(commitID).Run(&RunOpts{
|
||||
err := NewCommand("log", "--name-status", "-m", "--pretty=format:", "--first-parent", "--no-renames", "-z", "-1").AddDynamicArguments(commitID).Run(ctx, &RunOpts{
|
||||
Dir: repoPath,
|
||||
Stdout: w,
|
||||
Stderr: stderr,
|
||||
@ -457,7 +457,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(ctx, "rev-parse").AddDynamicArguments(shortID).RunStdString(&RunOpts{Dir: repoPath})
|
||||
commitID, _, err := NewCommand("rev-parse").AddDynamicArguments(shortID).RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "exit status 128") {
|
||||
return "", ErrNotExist{shortID, ""}
|
||||
|
@ -65,7 +65,7 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, commit *Commit, treePath
|
||||
log.Debug("missing commit for %s", entry.Name())
|
||||
}
|
||||
|
||||
// If the entry if a submodule add a submodule file for this
|
||||
// If the entry is a submodule add a submodule file for this
|
||||
if entry.IsSubModule() {
|
||||
subModuleURL := ""
|
||||
var fullPath string
|
||||
@ -85,8 +85,8 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, commit *Commit, treePath
|
||||
}
|
||||
|
||||
// Retrieve the commit for the treePath itself (see above). We basically
|
||||
// get it for free during the tree traversal and it's used for listing
|
||||
// pages to display information about newest commit for a given path.
|
||||
// get it for free during the tree traversal, and it's used for listing
|
||||
// pages to display information about the newest commit for a given path.
|
||||
var treeCommit *Commit
|
||||
var ok bool
|
||||
if treePath == "" {
|
||||
|
@ -116,7 +116,7 @@ func syncGitConfig() (err error) {
|
||||
}
|
||||
|
||||
func configSet(key, value string) error {
|
||||
stdout, _, err := NewCommand(DefaultContext, "config", "--global", "--get").AddDynamicArguments(key).RunStdString(nil)
|
||||
stdout, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(DefaultContext, nil)
|
||||
if err != nil && !IsErrorExitCode(err, 1) {
|
||||
return fmt.Errorf("failed to get git config %s, err: %w", key, err)
|
||||
}
|
||||
@ -126,7 +126,7 @@ func configSet(key, value string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, _, err = NewCommand(DefaultContext, "config", "--global").AddDynamicArguments(key, value).RunStdString(nil)
|
||||
_, _, err = NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(DefaultContext, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set git global config %s, err: %w", key, err)
|
||||
}
|
||||
@ -135,14 +135,14 @@ func configSet(key, value string) error {
|
||||
}
|
||||
|
||||
func configSetNonExist(key, value string) error {
|
||||
_, _, err := NewCommand(DefaultContext, "config", "--global", "--get").AddDynamicArguments(key).RunStdString(nil)
|
||||
_, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(DefaultContext, nil)
|
||||
if err == nil {
|
||||
// already exist
|
||||
return nil
|
||||
}
|
||||
if IsErrorExitCode(err, 1) {
|
||||
// not exist, set new config
|
||||
_, _, err = NewCommand(DefaultContext, "config", "--global").AddDynamicArguments(key, value).RunStdString(nil)
|
||||
_, _, err = NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(DefaultContext, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set git global config %s, err: %w", key, err)
|
||||
}
|
||||
@ -153,14 +153,14 @@ func configSetNonExist(key, value string) error {
|
||||
}
|
||||
|
||||
func configAddNonExist(key, value string) error {
|
||||
_, _, err := NewCommand(DefaultContext, "config", "--global", "--get").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(nil)
|
||||
_, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(DefaultContext, nil)
|
||||
if err == nil {
|
||||
// already exist
|
||||
return nil
|
||||
}
|
||||
if IsErrorExitCode(err, 1) {
|
||||
// not exist, add new config
|
||||
_, _, err = NewCommand(DefaultContext, "config", "--global", "--add").AddDynamicArguments(key, value).RunStdString(nil)
|
||||
_, _, err = NewCommand("config", "--global", "--add").AddDynamicArguments(key, value).RunStdString(DefaultContext, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add git global config %s, err: %w", key, err)
|
||||
}
|
||||
@ -170,10 +170,10 @@ func configAddNonExist(key, value string) error {
|
||||
}
|
||||
|
||||
func configUnsetAll(key, value string) error {
|
||||
_, _, err := NewCommand(DefaultContext, "config", "--global", "--get").AddDynamicArguments(key).RunStdString(nil)
|
||||
_, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(DefaultContext, nil)
|
||||
if err == nil {
|
||||
// exist, need to remove
|
||||
_, _, err = NewCommand(DefaultContext, "config", "--global", "--unset-all").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(nil)
|
||||
_, _, err = NewCommand("config", "--global", "--unset-all").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(DefaultContext, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unset git global config %s, err: %w", key, err)
|
||||
}
|
||||
|
@ -34,8 +34,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(ctx, "show", "--pretty=format:revert %H%n", "-R").AddDynamicArguments(commitID)
|
||||
if err := cmd.Run(&RunOpts{
|
||||
cmd := NewCommand("show", "--pretty=format:revert %H%n", "-R").AddDynamicArguments(commitID)
|
||||
if err := cmd.Run(ctx, &RunOpts{
|
||||
Dir: repoPath,
|
||||
Stdout: writer,
|
||||
Stderr: stderr,
|
||||
@ -56,7 +56,7 @@ func GetRepoRawDiffForFile(repo *Repository, startCommit, endCommit string, diff
|
||||
files = append(files, file)
|
||||
}
|
||||
|
||||
cmd := NewCommand(repo.Ctx)
|
||||
cmd := NewCommand()
|
||||
switch diffType {
|
||||
case RawDiffNormal:
|
||||
if len(startCommit) != 0 {
|
||||
@ -89,7 +89,7 @@ func GetRepoRawDiffForFile(repo *Repository, startCommit, endCommit string, diff
|
||||
}
|
||||
|
||||
stderr := new(bytes.Buffer)
|
||||
if err = cmd.Run(&RunOpts{
|
||||
if err = cmd.Run(repo.Ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: writer,
|
||||
Stderr: stderr,
|
||||
@ -301,8 +301,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(repo.Ctx, "diff", "--name-only").AddDynamicArguments(oldCommitID, newCommitID).
|
||||
Run(&RunOpts{
|
||||
err = NewCommand("diff", "--name-only").AddDynamicArguments(oldCommitID, newCommitID).
|
||||
Run(repo.Ctx, &RunOpts{
|
||||
Env: env,
|
||||
Dir: repo.Path,
|
||||
Stdout: stdoutWriter,
|
||||
|
@ -10,5 +10,5 @@ import (
|
||||
|
||||
// Fsck verifies the connectivity and validity of the objects in the database
|
||||
func Fsck(ctx context.Context, repoPath string, timeout time.Duration, args TrustedCmdArgs) error {
|
||||
return NewCommand(ctx, "fsck").AddArguments(args...).Run(&RunOpts{Timeout: timeout, Dir: repoPath})
|
||||
return NewCommand("fsck").AddArguments(args...).Run(ctx, &RunOpts{Timeout: timeout, Dir: repoPath})
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ func DefaultFeatures() *Features {
|
||||
}
|
||||
|
||||
func loadGitVersionFeatures() (*Features, error) {
|
||||
stdout, _, runErr := NewCommand(DefaultContext, "version").RunStdString(nil)
|
||||
stdout, _, runErr := NewCommand("version").RunStdString(DefaultContext, nil)
|
||||
if runErr != nil {
|
||||
return nil, runErr
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepO
|
||||
2^@repo: go-gitea/gitea
|
||||
*/
|
||||
var results []*GrepResult
|
||||
cmd := NewCommand(ctx, "grep", "--null", "--break", "--heading", "--fixed-strings", "--line-number", "--ignore-case", "--full-name")
|
||||
cmd := NewCommand("grep", "--null", "--break", "--heading", "--fixed-strings", "--line-number", "--ignore-case", "--full-name")
|
||||
cmd.AddOptionValues("--context", fmt.Sprint(opts.ContextLineNumber))
|
||||
if opts.IsFuzzy {
|
||||
words := strings.Fields(search)
|
||||
@ -66,7 +66,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(&RunOpts{
|
||||
err = cmd.Run(ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: stdoutWriter,
|
||||
Stderr: &stderr,
|
||||
|
@ -34,7 +34,7 @@ func LogNameStatusRepo(ctx context.Context, repository, head, treepath string, p
|
||||
_ = stdoutWriter.Close()
|
||||
}
|
||||
|
||||
cmd := NewCommand(ctx)
|
||||
cmd := NewCommand()
|
||||
cmd.AddArguments("log", "--name-status", "-c", "--format=commit%x00%H %P%x00", "--parents", "--no-renames", "-t", "-z").AddDynamicArguments(head)
|
||||
|
||||
var files []string
|
||||
@ -64,7 +64,7 @@ func LogNameStatusRepo(ctx context.Context, repository, head, treepath string, p
|
||||
|
||||
go func() {
|
||||
stderr := strings.Builder{}
|
||||
err := cmd.Run(&RunOpts{
|
||||
err := cmd.Run(ctx, &RunOpts{
|
||||
Dir: repository,
|
||||
Stdout: stdoutWriter,
|
||||
Stderr: &stderr,
|
||||
|
@ -25,8 +25,8 @@ func CatFileBatchCheck(ctx context.Context, shasToCheckReader *io.PipeReader, ca
|
||||
|
||||
stderr := new(bytes.Buffer)
|
||||
var errbuf strings.Builder
|
||||
cmd := git.NewCommand(ctx, "cat-file", "--batch-check")
|
||||
if err := cmd.Run(&git.RunOpts{
|
||||
cmd := git.NewCommand("cat-file", "--batch-check")
|
||||
if err := cmd.Run(ctx, &git.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(ctx, "cat-file", "--batch-check", "--batch-all-objects")
|
||||
if err := cmd.Run(&git.RunOpts{
|
||||
cmd := git.NewCommand("cat-file", "--batch-check", "--batch-all-objects")
|
||||
if err := cmd.Run(ctx, &git.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(ctx, "cat-file", "--batch").Run(&git.RunOpts{
|
||||
if err := git.NewCommand("cat-file", "--batch").Run(ctx, &git.RunOpts{
|
||||
Dir: tmpBasePath,
|
||||
Stdout: catFileBatchWriter,
|
||||
Stdin: shasToBatchReader,
|
||||
|
@ -32,7 +32,7 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
|
||||
|
||||
go func() {
|
||||
stderr := strings.Builder{}
|
||||
err := git.NewCommand(repo.Ctx, "rev-list", "--all").Run(&git.RunOpts{
|
||||
err := git.NewCommand("rev-list", "--all").Run(repo.Ctx, &git.RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: revListWriter,
|
||||
Stderr: &stderr,
|
||||
|
@ -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(ctx, "name-rev", "--stdin", "--name-only", "--always").Run(&git.RunOpts{
|
||||
if err := git.NewCommand("name-rev", "--stdin", "--name-only", "--always").Run(ctx, &git.RunOpts{
|
||||
Dir: tmpBasePath,
|
||||
Stdout: nameRevStdinWriter,
|
||||
Stdin: shasToNameReader,
|
||||
|
@ -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(ctx, "rev-list", "--objects", "--all")
|
||||
if err := cmd.Run(&git.RunOpts{
|
||||
cmd := git.NewCommand("rev-list", "--objects", "--all")
|
||||
if err := cmd.Run(ctx, &git.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(ctx, "rev-list", "--objects").AddDynamicArguments(headSHA)
|
||||
cmd := git.NewCommand("rev-list", "--objects").AddDynamicArguments(headSHA)
|
||||
if baseSHA != "" {
|
||||
cmd = cmd.AddArguments("--not").AddDynamicArguments(baseSHA)
|
||||
}
|
||||
if err := cmd.Run(&git.RunOpts{
|
||||
if err := cmd.Run(ctx, &git.RunOpts{
|
||||
Dir: tmpBasePath,
|
||||
Stdout: revListWriter,
|
||||
Stderr: stderr,
|
||||
|
@ -17,12 +17,12 @@ import (
|
||||
func GetRemoteAddress(ctx context.Context, repoPath, remoteName string) (string, error) {
|
||||
var cmd *Command
|
||||
if DefaultFeatures().CheckVersionAtLeast("2.7") {
|
||||
cmd = NewCommand(ctx, "remote", "get-url").AddDynamicArguments(remoteName)
|
||||
cmd = NewCommand("remote", "get-url").AddDynamicArguments(remoteName)
|
||||
} else {
|
||||
cmd = NewCommand(ctx, "config", "--get").AddDynamicArguments("remote." + remoteName + ".url")
|
||||
cmd = NewCommand("config", "--get").AddDynamicArguments("remote." + remoteName + ".url")
|
||||
}
|
||||
|
||||
result, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
|
||||
result, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -57,7 +57,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(ctx, "ls-remote", "-q", "-h").AddDynamicArguments(url, "HEAD").RunStdString(nil)
|
||||
_, _, err := NewCommand("ls-remote", "-q", "-h").AddDynamicArguments(url, "HEAD").RunStdString(ctx, nil)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ func InitRepository(ctx context.Context, repoPath string, bare bool, objectForma
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := NewCommand(ctx, "init")
|
||||
cmd := NewCommand("init")
|
||||
|
||||
if !IsValidObjectFormat(objectFormatName) {
|
||||
return fmt.Errorf("invalid object format: %s", objectFormatName)
|
||||
@ -80,15 +80,15 @@ func InitRepository(ctx context.Context, repoPath string, bare bool, objectForma
|
||||
if bare {
|
||||
cmd.AddArguments("--bare")
|
||||
}
|
||||
_, _, err = cmd.RunStdString(&RunOpts{Dir: repoPath})
|
||||
_, _, err = cmd.RunStdString(ctx, &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(repo.Ctx).AddOptionFormat("--git-dir=%s", repo.Path).AddArguments("rev-list", "-n", "1", "--all").
|
||||
Run(&RunOpts{
|
||||
if err := NewCommand().AddOptionFormat("--git-dir=%s", repo.Path).AddArguments("rev-list", "-n", "1", "--all").
|
||||
Run(repo.Ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: &output,
|
||||
Stderr: &errbuf,
|
||||
@ -129,7 +129,7 @@ func CloneWithArgs(ctx context.Context, args TrustedCmdArgs, from, to string, op
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := NewCommandContextNoGlobals(ctx, args...).AddArguments("clone")
|
||||
cmd := NewCommandNoGlobals(args...).AddArguments("clone")
|
||||
if opts.SkipTLSVerify {
|
||||
cmd.AddArguments("-c", "http.sslVerify=false")
|
||||
}
|
||||
@ -170,7 +170,7 @@ func CloneWithArgs(ctx context.Context, args TrustedCmdArgs, from, to string, op
|
||||
}
|
||||
|
||||
stderr := new(bytes.Buffer)
|
||||
if err = cmd.Run(&RunOpts{
|
||||
if err = cmd.Run(ctx, &RunOpts{
|
||||
Timeout: opts.Timeout,
|
||||
Env: envs,
|
||||
Stdout: io.Discard,
|
||||
@ -193,7 +193,7 @@ type PushOptions struct {
|
||||
|
||||
// Push pushs local commits to given remote branch.
|
||||
func Push(ctx context.Context, repoPath string, opts PushOptions) error {
|
||||
cmd := NewCommand(ctx, "push")
|
||||
cmd := NewCommand("push")
|
||||
if opts.Force {
|
||||
cmd.AddArguments("-f")
|
||||
}
|
||||
@ -206,7 +206,7 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error {
|
||||
}
|
||||
cmd.AddDashesAndList(remoteBranchArgs...)
|
||||
|
||||
stdout, stderr, err := cmd.RunStdString(&RunOpts{Env: opts.Env, Timeout: opts.Timeout, Dir: repoPath})
|
||||
stdout, stderr, err := cmd.RunStdString(ctx, &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}
|
||||
@ -225,8 +225,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(ctx, "for-each-ref", "--sort=-committerdate", BranchPrefix, "--count", "1", "--format=%(committerdate)")
|
||||
stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
|
||||
cmd := NewCommand("for-each-ref", "--sort=-committerdate", BranchPrefix, "--count", "1", "--format=%(committerdate)")
|
||||
stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
@ -242,9 +242,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(ctx, "rev-list", "--count", "--left-right").
|
||||
cmd := NewCommand("rev-list", "--count", "--left-right").
|
||||
AddDynamicArguments(baseBranch + "..." + targetBranch).AddArguments("--")
|
||||
stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
|
||||
stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
return do, err
|
||||
}
|
||||
@ -273,23 +273,23 @@ func (repo *Repository) CreateBundle(ctx context.Context, commit string, out io.
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
env := append(os.Environ(), "GIT_OBJECT_DIRECTORY="+filepath.Join(repo.Path, "objects"))
|
||||
_, _, err = NewCommand(ctx, "init", "--bare").RunStdString(&RunOpts{Dir: tmp, Env: env})
|
||||
_, _, err = NewCommand("init", "--bare").RunStdString(ctx, &RunOpts{Dir: tmp, Env: env})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = NewCommand(ctx, "reset", "--soft").AddDynamicArguments(commit).RunStdString(&RunOpts{Dir: tmp, Env: env})
|
||||
_, _, err = NewCommand("reset", "--soft").AddDynamicArguments(commit).RunStdString(ctx, &RunOpts{Dir: tmp, Env: env})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = NewCommand(ctx, "branch", "-m", "bundle").RunStdString(&RunOpts{Dir: tmp, Env: env})
|
||||
_, _, err = NewCommand("branch", "-m", "bundle").RunStdString(ctx, &RunOpts{Dir: tmp, Env: env})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tmpFile := filepath.Join(tmp, "bundle")
|
||||
_, _, err = NewCommand(ctx, "bundle", "create").AddDynamicArguments(tmpFile, "bundle", "HEAD").RunStdString(&RunOpts{Dir: tmp, Env: env})
|
||||
_, _, err = NewCommand("bundle", "create").AddDynamicArguments(tmpFile, "bundle", "HEAD").RunStdString(ctx, &RunOpts{Dir: tmp, Env: env})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ func (repo *Repository) CreateArchive(ctx context.Context, format ArchiveType, t
|
||||
return fmt.Errorf("unknown format: %v", format)
|
||||
}
|
||||
|
||||
cmd := NewCommand(ctx, "archive")
|
||||
cmd := NewCommand("archive")
|
||||
if usePrefix {
|
||||
cmd.AddOptionFormat("--prefix=%s", filepath.Base(strings.TrimSuffix(repo.Path, ".git"))+"/")
|
||||
}
|
||||
@ -61,7 +61,7 @@ func (repo *Repository) CreateArchive(ctx context.Context, format ArchiveType, t
|
||||
cmd.AddDynamicArguments(commitID)
|
||||
|
||||
var stderr strings.Builder
|
||||
err := cmd.Run(&RunOpts{
|
||||
err := cmd.Run(ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: target,
|
||||
Stderr: &stderr,
|
||||
|
@ -41,7 +41,7 @@ func (repo *Repository) CheckAttribute(opts CheckAttributeOpts) (map[string]map[
|
||||
stdOut := new(bytes.Buffer)
|
||||
stdErr := new(bytes.Buffer)
|
||||
|
||||
cmd := NewCommand(repo.Ctx, "check-attr", "-z")
|
||||
cmd := NewCommand("check-attr", "-z")
|
||||
|
||||
if opts.AllAttributes {
|
||||
cmd.AddArguments("-a")
|
||||
@ -59,7 +59,7 @@ func (repo *Repository) CheckAttribute(opts CheckAttributeOpts) (map[string]map[
|
||||
|
||||
cmd.AddDashesAndList(opts.Filenames...)
|
||||
|
||||
if err := cmd.Run(&RunOpts{
|
||||
if err := cmd.Run(repo.Ctx, &RunOpts{
|
||||
Env: env,
|
||||
Dir: repo.Path,
|
||||
Stdout: stdOut,
|
||||
@ -122,7 +122,7 @@ func (c *CheckAttributeReader) Init(ctx context.Context) error {
|
||||
}
|
||||
|
||||
c.ctx, c.cancel = context.WithCancel(ctx)
|
||||
c.cmd = NewCommand(c.ctx, "check-attr", "--stdin", "-z")
|
||||
c.cmd = NewCommand("check-attr", "--stdin", "-z")
|
||||
|
||||
if len(c.IndexFile) > 0 {
|
||||
c.cmd.AddArguments("--cached")
|
||||
@ -159,7 +159,7 @@ func (c *CheckAttributeReader) Run() error {
|
||||
_ = c.stdOut.Close()
|
||||
}()
|
||||
stdErr := new(bytes.Buffer)
|
||||
err := c.cmd.Run(&RunOpts{
|
||||
err := c.cmd.Run(c.ctx, &RunOpts{
|
||||
Env: c.env,
|
||||
Dir: c.Repo.Path,
|
||||
Stdin: c.stdinReader,
|
||||
|
@ -9,10 +9,10 @@ import (
|
||||
|
||||
// LineBlame returns the latest commit at the given line
|
||||
func (repo *Repository) LineBlame(revision, path, file string, line uint) (*Commit, error) {
|
||||
res, _, err := NewCommand(repo.Ctx, "blame").
|
||||
res, _, err := NewCommand("blame").
|
||||
AddOptionFormat("-L %d,%d", line, line).
|
||||
AddOptionValues("-p", revision).
|
||||
AddDashesAndList(file).RunStdString(&RunOpts{Dir: path})
|
||||
AddDashesAndList(file).RunStdString(repo.Ctx, &RunOpts{Dir: path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -16,7 +16,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(ctx, "show-ref", "--verify").AddDashesAndList(name).RunStdString(&RunOpts{Dir: repoPath})
|
||||
_, _, err := NewCommand("show-ref", "--verify").AddDashesAndList(name).RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
return err == nil
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ func (repo *Repository) GetHEADBranch() (*Branch, error) {
|
||||
if repo == nil {
|
||||
return nil, fmt.Errorf("nil repo")
|
||||
}
|
||||
stdout, _, err := NewCommand(repo.Ctx, "symbolic-ref", "HEAD").RunStdString(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := NewCommand("symbolic-ref", "HEAD").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -56,7 +56,7 @@ func (repo *Repository) GetHEADBranch() (*Branch, error) {
|
||||
}
|
||||
|
||||
func GetDefaultBranch(ctx context.Context, repoPath string) (string, error) {
|
||||
stdout, _, err := NewCommand(ctx, "symbolic-ref", "HEAD").RunStdString(&RunOpts{Dir: repoPath})
|
||||
stdout, _, err := NewCommand("symbolic-ref", "HEAD").RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -105,7 +105,7 @@ type DeleteBranchOptions struct {
|
||||
|
||||
// DeleteBranch delete a branch by name on repository.
|
||||
func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) error {
|
||||
cmd := NewCommand(repo.Ctx, "branch")
|
||||
cmd := NewCommand("branch")
|
||||
|
||||
if opts.Force {
|
||||
cmd.AddArguments("-D")
|
||||
@ -114,36 +114,36 @@ func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) erro
|
||||
}
|
||||
|
||||
cmd.AddDashesAndList(name)
|
||||
_, _, err := cmd.RunStdString(&RunOpts{Dir: repo.Path})
|
||||
_, _, err := cmd.RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateBranch create a new branch
|
||||
func (repo *Repository) CreateBranch(branch, oldbranchOrCommit string) error {
|
||||
cmd := NewCommand(repo.Ctx, "branch")
|
||||
cmd := NewCommand("branch")
|
||||
cmd.AddDashesAndList(branch, oldbranchOrCommit)
|
||||
|
||||
_, _, err := cmd.RunStdString(&RunOpts{Dir: repo.Path})
|
||||
_, _, err := cmd.RunStdString(repo.Ctx, &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(repo.Ctx, "remote", "add")
|
||||
cmd := NewCommand("remote", "add")
|
||||
if fetch {
|
||||
cmd.AddArguments("-f")
|
||||
}
|
||||
cmd.AddDynamicArguments(name, url)
|
||||
|
||||
_, _, err := cmd.RunStdString(&RunOpts{Dir: repo.Path})
|
||||
_, _, err := cmd.RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
return err
|
||||
}
|
||||
|
||||
// RemoveRemote removes a remote from repository.
|
||||
func (repo *Repository) RemoveRemote(name string) error {
|
||||
_, _, err := NewCommand(repo.Ctx, "remote", "rm").AddDynamicArguments(name).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
_, _, err := NewCommand("remote", "rm").AddDynamicArguments(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -154,6 +154,6 @@ func (branch *Branch) GetCommit() (*Commit, error) {
|
||||
|
||||
// RenameBranch rename a branch
|
||||
func (repo *Repository) RenameBranch(from, to string) error {
|
||||
_, _, err := NewCommand(repo.Ctx, "branch", "-m").AddDynamicArguments(from, to).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
_, _, err := NewCommand("branch", "-m").AddDynamicArguments(from, to).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
return err
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ func WalkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs,
|
||||
stderrBuilder := &strings.Builder{}
|
||||
args := TrustedCmdArgs{"for-each-ref", "--format=%(objectname) %(refname)"}
|
||||
args = append(args, extraArgs...)
|
||||
err := NewCommand(ctx, args...).Run(&RunOpts{
|
||||
err := NewCommand(args...).Run(ctx, &RunOpts{
|
||||
Dir: repoPath,
|
||||
Stdout: stdoutWriter,
|
||||
Stderr: stderrBuilder,
|
||||
|
@ -59,7 +59,7 @@ func (repo *Repository) getCommitByPathWithID(id ObjectID, relpath string) (*Com
|
||||
relpath = `\` + relpath
|
||||
}
|
||||
|
||||
stdout, _, runErr := NewCommand(repo.Ctx, "log", "-1", prettyLogFormat).AddDynamicArguments(id.String()).AddDashesAndList(relpath).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, runErr := NewCommand("log", "-1", prettyLogFormat).AddDynamicArguments(id.String()).AddDashesAndList(relpath).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if runErr != nil {
|
||||
return nil, runErr
|
||||
}
|
||||
@ -74,7 +74,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(repo.Ctx, "log", "-1", prettyLogFormat).AddDashesAndList(relpath).RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, runErr := NewCommand("log", "-1", prettyLogFormat).AddDashesAndList(relpath).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if runErr != nil {
|
||||
return nil, runErr
|
||||
}
|
||||
@ -90,7 +90,7 @@ func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) {
|
||||
}
|
||||
|
||||
func (repo *Repository) commitsByRange(id ObjectID, page, pageSize int, not string) ([]*Commit, error) {
|
||||
cmd := NewCommand(repo.Ctx, "log").
|
||||
cmd := NewCommand("log").
|
||||
AddOptionFormat("--skip=%d", (page-1)*pageSize).
|
||||
AddOptionFormat("--max-count=%d", pageSize).
|
||||
AddArguments(prettyLogFormat).
|
||||
@ -100,7 +100,7 @@ func (repo *Repository) commitsByRange(id ObjectID, page, pageSize int, not stri
|
||||
cmd.AddOptionValues("--not", not)
|
||||
}
|
||||
|
||||
stdout, _, err := cmd.RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -134,7 +134,7 @@ func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([
|
||||
}
|
||||
|
||||
// create new git log command with limit of 100 commits
|
||||
cmd := NewCommand(repo.Ctx, "log", "-100", prettyLogFormat).AddDynamicArguments(id.String())
|
||||
cmd := 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
|
||||
@ -154,7 +154,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(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -168,14 +168,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(repo.Ctx, "log", "-1", prettyLogFormat)
|
||||
hashCmd := 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(&RunOpts{Dir: repo.Path})
|
||||
hashMatching, _, err := hashCmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil || bytes.Contains(stdout, hashMatching) {
|
||||
continue
|
||||
}
|
||||
@ -190,7 +190,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(repo.Ctx, "diff", "--name-only", "-z").AddDynamicArguments(id1, id2).AddDashesAndList(filename).RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := NewCommand("diff", "--name-only", "-z").AddDynamicArguments(id1, id2).AddDashesAndList(filename).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -223,7 +223,7 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions)
|
||||
}()
|
||||
go func() {
|
||||
stderr := strings.Builder{}
|
||||
gitCmd := NewCommand(repo.Ctx, "rev-list").
|
||||
gitCmd := NewCommand("rev-list").
|
||||
AddOptionFormat("--max-count=%d", setting.Git.CommitsRangeSize).
|
||||
AddOptionFormat("--skip=%d", (opts.Page-1)*setting.Git.CommitsRangeSize)
|
||||
gitCmd.AddDynamicArguments(opts.Revision)
|
||||
@ -233,7 +233,7 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions)
|
||||
}
|
||||
|
||||
gitCmd.AddDashesAndList(opts.File)
|
||||
err := gitCmd.Run(&RunOpts{
|
||||
err := gitCmd.Run(repo.Ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: stdoutWriter,
|
||||
Stderr: &stderr,
|
||||
@ -275,11 +275,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(repo.Ctx, "diff", "--name-only").AddDynamicArguments(startCommitID + "..." + endCommitID).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := NewCommand("diff", "--name-only").AddDynamicArguments(startCommitID+"..."+endCommitID).RunStdString(repo.Ctx, &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(repo.Ctx, "diff", "--name-only").AddDynamicArguments(startCommitID, endCommitID).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err = NewCommand("diff", "--name-only").AddDynamicArguments(startCommitID, endCommitID).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@ -293,13 +293,13 @@ func (repo *Repository) CommitsBetween(last, before *Commit) ([]*Commit, error)
|
||||
var stdout []byte
|
||||
var err error
|
||||
if before == nil {
|
||||
stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err = NewCommand("rev-list").AddDynamicArguments(last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
} else {
|
||||
stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(before.ID.String() + ".." + last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).RunStdBytes(repo.Ctx, &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(repo.Ctx, "rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
@ -313,22 +313,22 @@ func (repo *Repository) CommitsBetweenLimit(last, before *Commit, limit, skip in
|
||||
var stdout []byte
|
||||
var err error
|
||||
if before == nil {
|
||||
stdout, _, err = NewCommand(repo.Ctx, "rev-list").
|
||||
stdout, _, err = NewCommand("rev-list").
|
||||
AddOptionValues("--max-count", strconv.Itoa(limit)).
|
||||
AddOptionValues("--skip", strconv.Itoa(skip)).
|
||||
AddDynamicArguments(last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
AddDynamicArguments(last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
} else {
|
||||
stdout, _, err = NewCommand(repo.Ctx, "rev-list").
|
||||
stdout, _, err = NewCommand("rev-list").
|
||||
AddOptionValues("--max-count", strconv.Itoa(limit)).
|
||||
AddOptionValues("--skip", strconv.Itoa(skip)).
|
||||
AddDynamicArguments(before.ID.String() + ".." + last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
AddDynamicArguments(before.ID.String()+".."+last.ID.String()).RunStdBytes(repo.Ctx, &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(repo.Ctx, "rev-list").
|
||||
stdout, _, err = NewCommand("rev-list").
|
||||
AddOptionValues("--max-count", strconv.Itoa(limit)).
|
||||
AddOptionValues("--skip", strconv.Itoa(skip)).
|
||||
AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
@ -343,13 +343,13 @@ func (repo *Repository) CommitsBetweenNotBase(last, before *Commit, baseBranch s
|
||||
var stdout []byte
|
||||
var err error
|
||||
if before == nil {
|
||||
stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err = NewCommand("rev-list").AddDynamicArguments(last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
} else {
|
||||
stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &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(repo.Ctx, "rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
@ -395,13 +395,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(repo.Ctx, "log", prettyLogFormat)
|
||||
cmd := NewCommand("log", prettyLogFormat)
|
||||
if limit > 0 {
|
||||
cmd.AddOptionFormat("-%d", limit)
|
||||
}
|
||||
cmd.AddDynamicArguments(id.String())
|
||||
|
||||
stdout, _, runErr := cmd.RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, runErr := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if runErr != nil {
|
||||
return nil, runErr
|
||||
}
|
||||
@ -438,10 +438,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(repo.Ctx, "for-each-ref", "--format=%(refname:strip=2)").
|
||||
stdout, _, err := NewCommand("for-each-ref", "--format=%(refname:strip=2)").
|
||||
AddOptionFormat("--count=%d", limit).
|
||||
AddOptionValues("--contains", commitID, BranchPrefix).
|
||||
RunStdString(&RunOpts{
|
||||
RunStdString(repo.Ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Env: env,
|
||||
})
|
||||
@ -453,7 +453,7 @@ func (repo *Repository) getBranches(env []string, commitID string, limit int) ([
|
||||
return branches, nil
|
||||
}
|
||||
|
||||
stdout, _, err := NewCommand(repo.Ctx, "branch").AddOptionValues("--contains", commitID).RunStdString(&RunOpts{
|
||||
stdout, _, err := NewCommand("branch").AddOptionValues("--contains", commitID).RunStdString(repo.Ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Env: env,
|
||||
})
|
||||
@ -495,7 +495,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(repo.Ctx, "branch", "--contains").AddDynamicArguments(commitID, branch).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := NewCommand("branch", "--contains").AddDynamicArguments(commitID, branch).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -521,10 +521,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(repo.Ctx, "log", prettyLogFormat)
|
||||
cmd := NewCommand("log", prettyLogFormat)
|
||||
cmd.AddDynamicArguments(endCommitID)
|
||||
|
||||
stdout, _, runErr := cmd.RunStdBytes(&RunOpts{
|
||||
stdout, _, runErr := cmd.RunStdBytes(repo.Ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Env: env,
|
||||
})
|
||||
|
@ -59,7 +59,7 @@ func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
|
||||
}
|
||||
}
|
||||
|
||||
actualCommitID, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify").AddDynamicArguments(commitID).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
actualCommitID, _, err := NewCommand("rev-parse", "--verify").AddDynamicArguments(commitID).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
actualCommitID = strings.TrimSpace(actualCommitID)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "unknown revision or path") ||
|
||||
|
@ -16,7 +16,7 @@ import (
|
||||
|
||||
// ResolveReference resolves a name to a reference
|
||||
func (repo *Repository) ResolveReference(name string) (string, error) {
|
||||
stdout, _, err := NewCommand(repo.Ctx, "show-ref", "--hash").AddDynamicArguments(name).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := NewCommand("show-ref", "--hash").AddDynamicArguments(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "not a valid ref") {
|
||||
return "", ErrNotExist{name, ""}
|
||||
@ -52,13 +52,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(repo.Ctx, "update-ref").AddDynamicArguments(name, commitID).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
_, _, err := NewCommand("update-ref").AddDynamicArguments(name, commitID).RunStdString(repo.Ctx, &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(repo.Ctx, "update-ref", "--no-deref", "-d").AddDynamicArguments(name).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
_, _, err := NewCommand("update-ref", "--no-deref", "-d").AddDynamicArguments(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ func (repo *Repository) IsCommitExist(name string) bool {
|
||||
log.Error("IsCommitExist: %v", err)
|
||||
return false
|
||||
}
|
||||
_, _, err := NewCommand(repo.Ctx, "cat-file", "-e").AddDynamicArguments(name).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
_, _, err := NewCommand("cat-file", "-e").AddDynamicArguments(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
return err == nil
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
// this requires git v2.18 to be installed
|
||||
func WriteCommitGraph(ctx context.Context, repoPath string) error {
|
||||
if DefaultFeatures().CheckVersionAtLeast("2.18") {
|
||||
if _, _, err := NewCommand(ctx, "commit-graph", "write").RunStdString(&RunOpts{Dir: repoPath}); err != nil {
|
||||
if _, _, err := NewCommand("commit-graph", "write").RunStdString(ctx, &RunOpts{Dir: repoPath}); err != nil {
|
||||
return fmt.Errorf("unable to write commit-graph for '%s' : %w", repoPath, err)
|
||||
}
|
||||
}
|
||||
|
@ -39,13 +39,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(repo.Ctx, "fetch", "--no-tags").AddDynamicArguments(tmpRemote).AddDashesAndList(base + ":" + tmpBaseName).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
_, _, err := NewCommand("fetch", "--no-tags").AddDynamicArguments(tmpRemote).AddDashesAndList(base+":"+tmpBaseName).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err == nil {
|
||||
base = tmpBaseName
|
||||
}
|
||||
}
|
||||
|
||||
stdout, _, err := NewCommand(repo.Ctx, "merge-base").AddDashesAndList(base, head).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := NewCommand("merge-base").AddDashesAndList(base, head).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
return strings.TrimSpace(stdout), base, err
|
||||
}
|
||||
|
||||
@ -94,9 +94,9 @@ func (repo *Repository) GetCompareInfo(basePath, baseBranch, headBranch string,
|
||||
if !fileOnly {
|
||||
// avoid: ambiguous argument 'refs/a...refs/b': unknown revision or path not in the working tree. Use '--': 'git <command> [<revision>...] -- [<file>...]'
|
||||
var logs []byte
|
||||
logs, _, err = NewCommand(repo.Ctx, "log").AddArguments(prettyLogFormat).
|
||||
AddDynamicArguments(baseCommitID + separator + headBranch).AddArguments("--").
|
||||
RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
logs, _, err = NewCommand("log").AddArguments(prettyLogFormat).
|
||||
AddDynamicArguments(baseCommitID+separator+headBranch).AddArguments("--").
|
||||
RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -150,8 +150,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(repo.Ctx, "diff", "-z", "--name-only").AddDynamicArguments(base + separator + head).AddArguments("--").
|
||||
Run(&RunOpts{
|
||||
if err := NewCommand("diff", "-z", "--name-only").AddDynamicArguments(base+separator+head).AddArguments("--").
|
||||
Run(repo.Ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: w,
|
||||
Stderr: stderr,
|
||||
@ -161,7 +161,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(repo.Ctx, "diff", "-z", "--name-only").AddDynamicArguments(base, head).AddArguments("--").Run(&RunOpts{
|
||||
if err = NewCommand("diff", "-z", "--name-only").AddDynamicArguments(base, head).AddArguments("--").Run(repo.Ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: w,
|
||||
Stderr: stderr,
|
||||
@ -174,23 +174,15 @@ func (repo *Repository) GetDiffNumChangedFiles(base, head string, directComparis
|
||||
return w.numLines, nil
|
||||
}
|
||||
|
||||
// GetDiffShortStat counts number of changed files, number of additions and deletions
|
||||
func (repo *Repository) GetDiffShortStat(base, head string) (numFiles, totalAdditions, totalDeletions int, err error) {
|
||||
numFiles, totalAdditions, totalDeletions, err = GetDiffShortStat(repo.Ctx, repo.Path, nil, base+"..."+head)
|
||||
if err != nil && strings.Contains(err.Error(), "no merge base") {
|
||||
return GetDiffShortStat(repo.Ctx, repo.Path, nil, base, head)
|
||||
}
|
||||
return numFiles, totalAdditions, totalDeletions, err
|
||||
}
|
||||
|
||||
// GetDiffShortStat counts number of changed files, number of additions and deletions
|
||||
func GetDiffShortStat(ctx context.Context, repoPath string, trustedArgs TrustedCmdArgs, dynamicArgs ...string) (numFiles, totalAdditions, totalDeletions int, err error) {
|
||||
// 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) {
|
||||
// Now if we call:
|
||||
// $ git diff --shortstat 1ebb35b98889ff77299f24d82da426b434b0cca0...788b8b1440462d477f45b0088875
|
||||
// we get:
|
||||
// " 9902 files changed, 2034198 insertions(+), 298800 deletions(-)\n"
|
||||
cmd := NewCommand(ctx, "diff", "--shortstat").AddArguments(trustedArgs...).AddDynamicArguments(dynamicArgs...)
|
||||
stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
|
||||
cmd := NewCommand("diff", "--shortstat").AddArguments(trustedArgs...).AddDynamicArguments(dynamicArgs...)
|
||||
stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
@ -236,8 +228,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(repo.Ctx, "diff", "-p").AddDynamicArguments(compareArg).
|
||||
Run(&RunOpts{
|
||||
return NewCommand("diff", "-p").AddDynamicArguments(compareArg).
|
||||
Run(repo.Ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: w,
|
||||
Stderr: stderr,
|
||||
@ -246,7 +238,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(repo.Ctx, "diff", "-p", "--binary", "--histogram").AddDynamicArguments(compareArg).Run(&RunOpts{
|
||||
return NewCommand("diff", "-p", "--binary", "--histogram").AddDynamicArguments(compareArg).Run(repo.Ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: w,
|
||||
})
|
||||
@ -255,8 +247,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(repo.Ctx, "format-patch", "--binary", "--stdout").AddDynamicArguments(compareArg).
|
||||
Run(&RunOpts{
|
||||
return NewCommand("format-patch", "--binary", "--stdout").AddDynamicArguments(compareArg).
|
||||
Run(repo.Ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: w,
|
||||
Stderr: stderr,
|
||||
@ -271,13 +263,13 @@ func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cmd := NewCommand(repo.Ctx, "diff-tree", "--name-only", "--root", "--no-commit-id", "-r", "-z")
|
||||
cmd := 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(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := cmd.RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ func (repo *Repository) GetDefaultPublicGPGKey(forceUpdate bool) (*GPGSettings,
|
||||
Sign: true,
|
||||
}
|
||||
|
||||
value, _, _ := NewCommand(repo.Ctx, "config", "--get", "commit.gpgsign").RunStdString(&RunOpts{Dir: repo.Path})
|
||||
value, _, _ := NewCommand("config", "--get", "commit.gpgsign").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
sign, valid := ParseBool(strings.TrimSpace(value))
|
||||
if !sign || !valid {
|
||||
gpgSettings.Sign = false
|
||||
@ -41,13 +41,13 @@ func (repo *Repository) GetDefaultPublicGPGKey(forceUpdate bool) (*GPGSettings,
|
||||
return gpgSettings, nil
|
||||
}
|
||||
|
||||
signingKey, _, _ := NewCommand(repo.Ctx, "config", "--get", "user.signingkey").RunStdString(&RunOpts{Dir: repo.Path})
|
||||
signingKey, _, _ := NewCommand("config", "--get", "user.signingkey").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
gpgSettings.KeyID = strings.TrimSpace(signingKey)
|
||||
|
||||
defaultEmail, _, _ := NewCommand(repo.Ctx, "config", "--get", "user.email").RunStdString(&RunOpts{Dir: repo.Path})
|
||||
defaultEmail, _, _ := NewCommand("config", "--get", "user.email").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
gpgSettings.Email = strings.TrimSpace(defaultEmail)
|
||||
|
||||
defaultName, _, _ := NewCommand(repo.Ctx, "config", "--get", "user.name").RunStdString(&RunOpts{Dir: repo.Path})
|
||||
defaultName, _, _ := NewCommand("config", "--get", "user.name").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
gpgSettings.Name = strings.TrimSpace(defaultName)
|
||||
|
||||
if err := gpgSettings.LoadPublicKeyContent(); err != nil {
|
||||
|
@ -22,7 +22,7 @@ func (repo *Repository) ReadTreeToIndex(treeish string, indexFilename ...string)
|
||||
}
|
||||
|
||||
if len(treeish) != objectFormat.FullLength() {
|
||||
res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify").AddDynamicArguments(treeish).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
res, _, err := NewCommand("rev-parse", "--verify").AddDynamicArguments(treeish).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -42,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(repo.Ctx, "read-tree").AddDynamicArguments(id.String()).RunStdString(&RunOpts{Dir: repo.Path, Env: env})
|
||||
_, _, err := NewCommand("read-tree").AddDynamicArguments(id.String()).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path, Env: env})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -83,14 +83,14 @@ func (repo *Repository) ReadTreeToTemporaryIndex(treeish string) (tmpIndexFilena
|
||||
|
||||
// EmptyIndex empties the index
|
||||
func (repo *Repository) EmptyIndex() error {
|
||||
_, _, err := NewCommand(repo.Ctx, "read-tree", "--empty").RunStdString(&RunOpts{Dir: repo.Path})
|
||||
_, _, err := NewCommand("read-tree", "--empty").RunStdString(repo.Ctx, &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(repo.Ctx, "ls-files", "-z").AddDashesAndList(filenames...)
|
||||
res, _, err := cmd.RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
cmd := NewCommand("ls-files", "-z").AddDashesAndList(filenames...)
|
||||
res, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -108,7 +108,7 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd := NewCommand(repo.Ctx, "update-index", "--remove", "-z", "--index-info")
|
||||
cmd := NewCommand("update-index", "--remove", "-z", "--index-info")
|
||||
stdout := new(bytes.Buffer)
|
||||
stderr := new(bytes.Buffer)
|
||||
buffer := new(bytes.Buffer)
|
||||
@ -118,7 +118,7 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error {
|
||||
buffer.WriteString("0 blob " + objectFormat.EmptyObjectID().String() + "\t" + file + "\000")
|
||||
}
|
||||
}
|
||||
return cmd.Run(&RunOpts{
|
||||
return cmd.Run(repo.Ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdin: bytes.NewReader(buffer.Bytes()),
|
||||
Stdout: stdout,
|
||||
@ -134,7 +134,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(repo.Ctx, "update-index", "--add", "--replace", "-z", "--index-info")
|
||||
cmd := NewCommand("update-index", "--add", "--replace", "-z", "--index-info")
|
||||
stdout := new(bytes.Buffer)
|
||||
stderr := new(bytes.Buffer)
|
||||
buffer := new(bytes.Buffer)
|
||||
@ -142,7 +142,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(&RunOpts{
|
||||
return cmd.Run(repo.Ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdin: bytes.NewReader(buffer.Bytes()),
|
||||
Stdout: stdout,
|
||||
@ -157,7 +157,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(repo.Ctx, "write-tree").RunStdString(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, runErr := NewCommand("write-tree").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if runErr != nil {
|
||||
return nil, runErr
|
||||
}
|
||||
|
@ -68,13 +68,13 @@ func (repo *Repository) HashObject(reader io.Reader) (ObjectID, error) {
|
||||
func (repo *Repository) hashObject(reader io.Reader, save bool) (string, error) {
|
||||
var cmd *Command
|
||||
if save {
|
||||
cmd = NewCommand(repo.Ctx, "hash-object", "-w", "--stdin")
|
||||
cmd = NewCommand("hash-object", "-w", "--stdin")
|
||||
} else {
|
||||
cmd = NewCommand(repo.Ctx, "hash-object", "--stdin")
|
||||
cmd = NewCommand("hash-object", "--stdin")
|
||||
}
|
||||
stdout := new(bytes.Buffer)
|
||||
stderr := new(bytes.Buffer)
|
||||
err := cmd.Run(&RunOpts{
|
||||
err := cmd.Run(repo.Ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdin: reader,
|
||||
Stdout: stdout,
|
||||
|
@ -18,7 +18,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(ctx)
|
||||
cmd := NewCommand()
|
||||
if refType == "branch" {
|
||||
cmd.AddArguments("branch")
|
||||
} else if refType == "tag" {
|
||||
@ -26,7 +26,7 @@ func (repo *Repository) ListOccurrences(ctx context.Context, refType, commitSHA
|
||||
} else {
|
||||
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(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := cmd.AddArguments("--no-color", "--sort=-creatordate", "--contains").AddDynamicArguments(commitSHA).RunStdString(ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ func (repo *Repository) GetRefsFiltered(pattern string) ([]*Reference, error) {
|
||||
|
||||
go func() {
|
||||
stderrBuilder := &strings.Builder{}
|
||||
err := NewCommand(repo.Ctx, "for-each-ref").Run(&RunOpts{
|
||||
err := NewCommand("for-each-ref").Run(repo.Ctx, &RunOpts{
|
||||
Dir: repo.Path,
|
||||
Stdout: stdoutWriter,
|
||||
Stderr: stderrBuilder,
|
||||
|
@ -40,7 +40,7 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string)
|
||||
|
||||
since := fromTime.Format(time.RFC3339)
|
||||
|
||||
stdout, _, runErr := NewCommand(repo.Ctx, "rev-list", "--count", "--no-merges", "--branches=*", "--date=iso").AddOptionFormat("--since='%s'", since).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, runErr := NewCommand("rev-list", "--count", "--no-merges", "--branches=*", "--date=iso").AddOptionFormat("--since='%s'", since).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if runErr != nil {
|
||||
return nil, runErr
|
||||
}
|
||||
@ -60,7 +60,7 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string)
|
||||
_ = stdoutWriter.Close()
|
||||
}()
|
||||
|
||||
gitCmd := NewCommand(repo.Ctx, "log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%aN%n%aE%n", "--date=iso").AddOptionFormat("--since='%s'", since)
|
||||
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=*")
|
||||
} else {
|
||||
@ -68,7 +68,7 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string)
|
||||
}
|
||||
|
||||
stderr := new(strings.Builder)
|
||||
err = gitCmd.Run(&RunOpts{
|
||||
err = gitCmd.Run(repo.Ctx, &RunOpts{
|
||||
Env: []string{},
|
||||
Dir: repo.Path,
|
||||
Stdout: stdoutWriter,
|
||||
|
@ -24,13 +24,13 @@ func IsTagExist(ctx context.Context, repoPath, name string) bool {
|
||||
|
||||
// CreateTag create one tag in the repository
|
||||
func (repo *Repository) CreateTag(name, revision string) error {
|
||||
_, _, err := NewCommand(repo.Ctx, "tag").AddDashesAndList(name, revision).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
_, _, err := NewCommand("tag").AddDashesAndList(name, revision).RunStdString(repo.Ctx, &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(repo.Ctx, "tag", "-a", "-m").AddDynamicArguments(message).AddDashesAndList(name, revision).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
_, _, err := NewCommand("tag", "-a", "-m").AddDynamicArguments(message).AddDashesAndList(name, revision).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
return err
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ func (repo *Repository) GetTagNameBySHA(sha string) (string, error) {
|
||||
return "", fmt.Errorf("SHA is too short: %s", sha)
|
||||
}
|
||||
|
||||
stdout, _, err := NewCommand(repo.Ctx, "show-ref", "--tags", "-d").RunStdString(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := NewCommand("show-ref", "--tags", "-d").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -63,7 +63,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(repo.Ctx, "show-ref", "--tags").AddDashesAndList(name).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
stdout, _, err := NewCommand("show-ref", "--tags").AddDashesAndList(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -123,9 +123,9 @@ func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, int, error) {
|
||||
rc := &RunOpts{Dir: repo.Path, Stdout: stdoutWriter, Stderr: &stderr}
|
||||
|
||||
go func() {
|
||||
err := NewCommand(repo.Ctx, "for-each-ref").
|
||||
err := NewCommand("for-each-ref").
|
||||
AddOptionFormat("--format=%s", forEachRefFmt.Flag()).
|
||||
AddArguments("--sort", "-*creatordate", "refs/tags").Run(rc)
|
||||
AddArguments("--sort", "-*creatordate", "refs/tags").Run(repo.Ctx, rc)
|
||||
if err != nil {
|
||||
_ = stdoutWriter.CloseWithError(ConcatenateError(err, stderr.String()))
|
||||
} else {
|
||||
|
@ -33,7 +33,7 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt
|
||||
"GIT_COMMITTER_EMAIL="+committer.Email,
|
||||
"GIT_COMMITTER_DATE="+commitTimeStr,
|
||||
)
|
||||
cmd := NewCommand(repo.Ctx, "commit-tree").AddDynamicArguments(tree.ID.String())
|
||||
cmd := NewCommand("commit-tree").AddDynamicArguments(tree.ID.String())
|
||||
|
||||
for _, parent := range opts.Parents {
|
||||
cmd.AddArguments("-p").AddDynamicArguments(parent)
|
||||
@ -53,7 +53,7 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt
|
||||
|
||||
stdout := new(bytes.Buffer)
|
||||
stderr := new(bytes.Buffer)
|
||||
err := cmd.Run(&RunOpts{
|
||||
err := cmd.Run(repo.Ctx, &RunOpts{
|
||||
Env: env,
|
||||
Dir: repo.Path,
|
||||
Stdin: messageBytes,
|
||||
|
@ -36,7 +36,7 @@ func (repo *Repository) GetTree(idStr string) (*Tree, error) {
|
||||
}
|
||||
|
||||
if len(idStr) != objectFormat.FullLength() {
|
||||
res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify").AddDynamicArguments(idStr).RunStdString(&RunOpts{Dir: repo.Path})
|
||||
res, _, err := NewCommand("rev-parse", "--verify").AddDynamicArguments(idStr).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ func GetTemplateSubmoduleCommits(ctx context.Context, repoPath string) (submodul
|
||||
return scanner.Err()
|
||||
},
|
||||
}
|
||||
err = NewCommand(ctx, "ls-tree", "-r", "--", "HEAD").Run(opts)
|
||||
err = 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 +56,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(ctx, "update-index", "--add", "--cacheinfo", "160000").AddDynamicArguments(submodule.Commit, submodule.Path)
|
||||
if stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath}); err != nil {
|
||||
cmd := NewCommand("update-index", "--add", "--cacheinfo", "160000").AddDynamicArguments(submodule.Commit, submodule.Path)
|
||||
if stdout, _, err := cmd.RunStdString(ctx, &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
|
||||
}
|
||||
|
@ -30,14 +30,14 @@ func TestAddTemplateSubmoduleIndexes(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
tmpDir := t.TempDir()
|
||||
var err error
|
||||
_, _, err = NewCommand(ctx, "init").RunStdString(&RunOpts{Dir: tmpDir})
|
||||
_, _, err = NewCommand("init").RunStdString(ctx, &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(ctx, "add", "--all").RunStdString(&RunOpts{Dir: tmpDir})
|
||||
_, _, err = NewCommand("add", "--all").RunStdString(ctx, &RunOpts{Dir: tmpDir})
|
||||
require.NoError(t, err)
|
||||
_, _, err = NewCommand(ctx, "-c", "user.name=a", "-c", "user.email=b", "commit", "-m=test").RunStdString(&RunOpts{Dir: tmpDir})
|
||||
_, _, err = NewCommand("-c", "user.name=a", "-c", "user.email=b", "commit", "-m=test").RunStdString(ctx, &RunOpts{Dir: tmpDir})
|
||||
require.NoError(t, err)
|
||||
submodules, err := GetTemplateSubmoduleCommits(DefaultContext, tmpDir)
|
||||
require.NoError(t, err)
|
||||
|
@ -48,10 +48,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(repo.Ctx, "ls-tree", "-z", "--name-only").
|
||||
cmd := NewCommand("ls-tree", "-z", "--name-only").
|
||||
AddDashesAndList(append([]string{ref}, filenames...)...)
|
||||
|
||||
res, _, err := cmd.RunStdBytes(&RunOpts{Dir: repo.Path})
|
||||
res, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -65,9 +65,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(repo.Ctx, "rev-list", "-1").
|
||||
stdout, _, err := NewCommand("rev-list", "-1").
|
||||
AddDynamicArguments(refName).AddDashesAndList(treePath).
|
||||
RunStdString(&RunOpts{Dir: repo.Path})
|
||||
RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ func (t *Tree) ListEntries() (Entries, error) {
|
||||
}
|
||||
}
|
||||
|
||||
stdout, _, runErr := NewCommand(t.repo.Ctx, "ls-tree", "-l").AddDynamicArguments(t.ID.String()).RunStdBytes(&RunOpts{Dir: t.repo.Path})
|
||||
stdout, _, runErr := NewCommand("ls-tree", "-l").AddDynamicArguments(t.ID.String()).RunStdBytes(t.repo.Ctx, &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{
|
||||
@ -96,10 +96,10 @@ func (t *Tree) listEntriesRecursive(extraArgs TrustedCmdArgs) (Entries, error) {
|
||||
return t.entriesRecursive, nil
|
||||
}
|
||||
|
||||
stdout, _, runErr := NewCommand(t.repo.Ctx, "ls-tree", "-t", "-r").
|
||||
stdout, _, runErr := NewCommand("ls-tree", "-t", "-r").
|
||||
AddArguments(extraArgs...).
|
||||
AddDynamicArguments(t.ID.String()).
|
||||
RunStdBytes(&RunOpts{Dir: t.repo.Path})
|
||||
RunStdBytes(t.repo.Ctx, &RunOpts{Dir: t.repo.Path})
|
||||
if runErr != nil {
|
||||
return nil, runErr
|
||||
}
|
||||
|
@ -33,9 +33,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(ctx, "symbolic-ref", "HEAD").
|
||||
AddDynamicArguments(git.BranchPrefix + name).
|
||||
RunStdString(&git.RunOpts{Dir: repoPath(repo)})
|
||||
_, _, err := git.NewCommand("symbolic-ref", "HEAD").
|
||||
AddDynamicArguments(git.BranchPrefix+name).
|
||||
RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)})
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
gohtml "html"
|
||||
"html/template"
|
||||
"io"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -83,7 +84,7 @@ func Code(fileName, language, code string) (output template.HTML, lexerName stri
|
||||
}
|
||||
|
||||
if lexer == nil {
|
||||
if val, ok := highlightMapping[filepath.Ext(fileName)]; ok {
|
||||
if val, ok := highlightMapping[path.Ext(fileName)]; ok {
|
||||
// use mapped value to find lexer
|
||||
lexer = lexers.Get(val)
|
||||
}
|
||||
|
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