mirror of
https://github.com/go-gitea/gitea.git
synced 2024-09-01 14:56:30 +00:00
Merge remote-tracking branch 'origin/main' into xormigrate
This commit is contained in:
commit
23e81c596a
@ -26,7 +26,7 @@
|
|||||||
fork_id: 0
|
fork_id: 0
|
||||||
is_template: false
|
is_template: false
|
||||||
template_id: 0
|
template_id: 0
|
||||||
size: 7320
|
size: 7597
|
||||||
is_fsck_enabled: true
|
is_fsck_enabled: true
|
||||||
close_issues_via_commit_in_any_branch: false
|
close_issues_via_commit_in_any_branch: false
|
||||||
|
|
||||||
|
@ -572,6 +572,8 @@ var migrations = []*xormigrate.Migration{
|
|||||||
NewMigration("Add index to action_task stopped log_expired", v1_23.AddIndexToActionTaskStoppedLogExpired),
|
NewMigration("Add index to action_task stopped log_expired", v1_23.AddIndexToActionTaskStoppedLogExpired),
|
||||||
// v303 -> v304
|
// v303 -> v304
|
||||||
NewMigration("Add metadata column for comment table", v1_23.AddCommentMetaDataColumn),
|
NewMigration("Add metadata column for comment table", v1_23.AddCommentMetaDataColumn),
|
||||||
|
// v304 -> v305
|
||||||
|
NewMigration("Add index for release sha1", v1_23.AddIndexForReleaseSha1),
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnsureUpToDate will check if the db is at the correct version
|
// EnsureUpToDate will check if the db is at the correct version
|
||||||
|
@ -3,303 +3,11 @@
|
|||||||
|
|
||||||
package v1_23 //nolint
|
package v1_23 //nolint
|
||||||
|
|
||||||
import (
|
import "xorm.io/xorm"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
func AddIndexForReleaseSha1(x *xorm.Engine) error {
|
||||||
"code.gitea.io/gitea/modules/setting"
|
type Release struct {
|
||||||
|
Sha1 string `xorm:"INDEX VARCHAR(64)"`
|
||||||
"src.techknowlogick.com/xormigrate"
|
}
|
||||||
"xorm.io/xorm"
|
return x.Sync(new(Release))
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
minDBVersion = 70 // Gitea 1.5.3
|
|
||||||
oldMigrationsCount = 230
|
|
||||||
expectedVersion = minDBVersion + oldMigrationsCount
|
|
||||||
)
|
|
||||||
|
|
||||||
var oldMigrationNames = []string{
|
|
||||||
"add issue_dependencies",
|
|
||||||
"protect each scratch token",
|
|
||||||
"add review",
|
|
||||||
"add must_change_password column for users table",
|
|
||||||
"add approval whitelists to protected branches",
|
|
||||||
"clear nonused data which not deleted when user was deleted",
|
|
||||||
"add pull request rebase with merge commit",
|
|
||||||
"add theme to users",
|
|
||||||
"rename repo is_bare to repo is_empty",
|
|
||||||
"add can close issues via commit in any branch",
|
|
||||||
"add is locked to issues",
|
|
||||||
"update U2F counter type",
|
|
||||||
"hot fix for wrong release sha1 on release table",
|
|
||||||
"add uploader id for table attachment",
|
|
||||||
"add table to store original imported gpg keys",
|
|
||||||
"hash application token",
|
|
||||||
"add http method to webhook",
|
|
||||||
"add avatar field to repository",
|
|
||||||
"add commit status context field to commit_status",
|
|
||||||
"add original author/url migration info to issues, comments, and repo ",
|
|
||||||
"change length of some repository columns",
|
|
||||||
"add index on owner_id of repository and type, review_id of comment",
|
|
||||||
"remove orphaned repository index statuses",
|
|
||||||
"add email notification enabled preference to user",
|
|
||||||
"add enable_status_check, status_check_contexts to protected_branch",
|
|
||||||
"add table columns for cross referencing issues",
|
|
||||||
"delete orphaned attachments",
|
|
||||||
"add repo_admin_change_team_access to user",
|
|
||||||
"add original author name and id on migrated release",
|
|
||||||
"add task table and status column for repository table",
|
|
||||||
"update migration repositories' service type",
|
|
||||||
"change length of some external login users columns",
|
|
||||||
"update migration repositories' service type v2",
|
|
||||||
"Add WhitelistDeployKeys to protected branch",
|
|
||||||
"remove unnecessary columns from label",
|
|
||||||
"add includes_all_repositories to teams",
|
|
||||||
"add column `mode` to table watch",
|
|
||||||
"Add template options to repository",
|
|
||||||
"Add comment_id on table notification",
|
|
||||||
"add can_create_org_repo to team",
|
|
||||||
"change review content type to text",
|
|
||||||
"update branch protection for can push and whitelist enable",
|
|
||||||
"remove release attachments which repository deleted",
|
|
||||||
"new feature: change target branch of pull requests",
|
|
||||||
"Remove authentication credentials from stored URL",
|
|
||||||
"add user_id prefix to existing user avatar name",
|
|
||||||
"Extend TrackedTimes",
|
|
||||||
"Add block on rejected reviews branch protection",
|
|
||||||
"Add commit id and stale to reviews",
|
|
||||||
"Fix migrated repositories' git service type",
|
|
||||||
"Add owner_name on table repository",
|
|
||||||
"add is_restricted column for users table",
|
|
||||||
"Add Require Signed Commits to ProtectedBranch",
|
|
||||||
"Add original information for reactions",
|
|
||||||
"Add columns to user and repository",
|
|
||||||
"Add some columns on review for migration",
|
|
||||||
"Fix topic repository count",
|
|
||||||
"add repository code language statistics",
|
|
||||||
"fix merge base for pull requests",
|
|
||||||
"remove dependencies from deleted repositories",
|
|
||||||
"Expand webhooks for more granularity",
|
|
||||||
"Add IsSystemWebhook column to webhooks table",
|
|
||||||
"Add Branch Protection Protected Files Column",
|
|
||||||
"Add EmailHash Table",
|
|
||||||
"Refix merge base for merged pull requests",
|
|
||||||
"Add OrgID column to Labels table",
|
|
||||||
"Add CommitsAhead and CommitsBehind Column to PullRequest Table",
|
|
||||||
"Add Branch Protection Block Outdated Branch",
|
|
||||||
"Add ResolveDoerID to Comment table",
|
|
||||||
"prepend refs/heads/ to issue refs",
|
|
||||||
"Save detected language file size to database instead of percent",
|
|
||||||
"Add KeepActivityPrivate to User table",
|
|
||||||
"Ensure Repository.IsArchived is not null",
|
|
||||||
"recalculate Stars number for all user",
|
|
||||||
"update Matrix Webhook http method to 'PUT'",
|
|
||||||
"Increase Language field to 50 in LanguageStats",
|
|
||||||
"Add projects info to repository table",
|
|
||||||
"create review for 0 review id code comments",
|
|
||||||
"remove issue dependency comments who refer to non existing issues",
|
|
||||||
"Add Created and Updated to Milestone table",
|
|
||||||
"add primary key to repo_topic",
|
|
||||||
"set default password algorithm to Argon2",
|
|
||||||
"add TrustModel field to Repository",
|
|
||||||
"add Team review request support",
|
|
||||||
"add timestamps to Star, Label, Follow, Watch and Collaboration",
|
|
||||||
"add changed_protected_files column for pull_request table",
|
|
||||||
"fix publisher ID for tag releases",
|
|
||||||
"ensure repo topics are up-to-date",
|
|
||||||
"code comment replies should have the commitID of the review they are replying to",
|
|
||||||
"update reactions constraint",
|
|
||||||
"Add block on official review requests branch protection",
|
|
||||||
"Convert task type from int to string",
|
|
||||||
"Convert webhook task type from int to string",
|
|
||||||
"Convert topic name from 25 to 50",
|
|
||||||
"Add scope and nonce columns to oauth2_grant table",
|
|
||||||
"Convert hook task type from char(16) to varchar(16) and trim the column",
|
|
||||||
"Where Password is Valid with Empty String delete it",
|
|
||||||
"Add user redirect",
|
|
||||||
"Recreate user table to fix default values",
|
|
||||||
"Update DeleteBranch comments to set the old_ref to the commit_sha",
|
|
||||||
"Add Dismissed to Review table",
|
|
||||||
"Add Sorting to ProjectBoard table",
|
|
||||||
"Add sessions table for go-chi/session",
|
|
||||||
"Add time_id column to Comment",
|
|
||||||
"Create repo transfer table",
|
|
||||||
"Fix Postgres ID Sequences broken by recreate-table",
|
|
||||||
"Remove invalid labels from comments",
|
|
||||||
"Delete orphaned IssueLabels",
|
|
||||||
"Add LFS columns to Mirror",
|
|
||||||
"Convert avatar url to text",
|
|
||||||
"Delete credentials from past migrations",
|
|
||||||
"Always save primary email on email address table",
|
|
||||||
"Add issue resource index table",
|
|
||||||
"Create PushMirror table",
|
|
||||||
"Rename Task errors to message",
|
|
||||||
"Add new table repo_archiver",
|
|
||||||
"Create protected tag table",
|
|
||||||
"Drop unneeded webhook related columns",
|
|
||||||
"Add key is verified to gpg key",
|
|
||||||
"Unwrap ldap.Sources",
|
|
||||||
"Add agit flow pull request support",
|
|
||||||
"Alter issue/comment table TEXT fields to LONGTEXT",
|
|
||||||
"RecreateIssueResourceIndexTable to have a primary key instead of an unique index",
|
|
||||||
"Add repo id column for attachment table",
|
|
||||||
"Add Branch Protection Unprotected Files Column",
|
|
||||||
"Add table commit_status_index",
|
|
||||||
"Add Color to ProjectBoard table",
|
|
||||||
"Add renamed_branch table",
|
|
||||||
"Add issue content history table",
|
|
||||||
"No-op (remote version is using AppState now)",
|
|
||||||
"Add table app_state",
|
|
||||||
"Drop table remote_version (if exists)",
|
|
||||||
"Create key/value table for user settings",
|
|
||||||
"Add Sorting to ProjectIssue table",
|
|
||||||
"Add key is verified to ssh key",
|
|
||||||
"Migrate to higher varchar on user struct",
|
|
||||||
"Add authorize column to team_unit table",
|
|
||||||
"Add webauthn table and migrate u2f data to webauthn - NO-OPED",
|
|
||||||
"Use base32.HexEncoding instead of base64 encoding for cred ID as it is case insensitive - NO-OPED",
|
|
||||||
"Increase WebAuthentication CredentialID size to 410 - NO-OPED",
|
|
||||||
"v208 was completely broken - remigrate",
|
|
||||||
"Create ForeignReference table",
|
|
||||||
"Add package tables",
|
|
||||||
"Add allow edits from maintainers to PullRequest table",
|
|
||||||
"Add auto merge table",
|
|
||||||
"allow to view files in PRs",
|
|
||||||
"No-op (Improve Action table indices v1)",
|
|
||||||
"Alter hook_task table TEXT fields to LONGTEXT",
|
|
||||||
"Improve Action table indices v2",
|
|
||||||
"Add sync_on_commit column to push_mirror table",
|
|
||||||
"Add container repository property",
|
|
||||||
"Store WebAuthentication CredentialID as bytes and increase size to at least 1024",
|
|
||||||
"Drop old CredentialID column",
|
|
||||||
"Rename CredentialIDBytes column to CredentialID",
|
|
||||||
"Add badges to users",
|
|
||||||
"Alter gpg_key/public_key content TEXT fields to MEDIUMTEXT",
|
|
||||||
"Conan and generic packages do not need to be semantically versioned",
|
|
||||||
"Create key/value table for system settings",
|
|
||||||
"Add TeamInvite table",
|
|
||||||
"Update counts of all open milestones",
|
|
||||||
"Add ConfidentialClient column (default true) to OAuth2Application table",
|
|
||||||
"Add index for hook_task",
|
|
||||||
"Alter package_version.metadata_json to LONGTEXT",
|
|
||||||
"Add header_authorization_encrypted column to webhook table",
|
|
||||||
"Add package cleanup rule table",
|
|
||||||
"Add index for access_token",
|
|
||||||
"Create secrets table",
|
|
||||||
"Drop ForeignReference table",
|
|
||||||
"Add updated unix to LFSMetaObject",
|
|
||||||
"Add scope for access_token",
|
|
||||||
"Add actions tables",
|
|
||||||
"Add card_type column to project table",
|
|
||||||
"Alter gpg_key_import content TEXT field to MEDIUMTEXT",
|
|
||||||
"Add exclusive label",
|
|
||||||
"Add NeedApproval to actions tables",
|
|
||||||
"Rename Webhook org_id to owner_id",
|
|
||||||
"Add missed column owner_id for project table",
|
|
||||||
"Fix incorrect project type",
|
|
||||||
"Add version column to action_runner table",
|
|
||||||
"Improve Action table indices v3",
|
|
||||||
"Change Container Metadata",
|
|
||||||
"Fix incorrect owner team unit access mode",
|
|
||||||
"Fix incorrect admin team unit access mode",
|
|
||||||
"Fix ExternalTracker and ExternalWiki accessMode in owner and admin team",
|
|
||||||
"Add ActionTaskOutput table",
|
|
||||||
"Add ArchivedUnix Column",
|
|
||||||
"Add is_internal column to package",
|
|
||||||
"Add Actions Artifact table",
|
|
||||||
"Add PinOrder Column",
|
|
||||||
"Convert scoped access tokens",
|
|
||||||
"Drop custom_labels column of action_runner table",
|
|
||||||
"Add variable table",
|
|
||||||
"Add TriggerEvent to action_run table",
|
|
||||||
"Add git_size and lfs_size columns to repository table",
|
|
||||||
"Add branch table",
|
|
||||||
"Alter Actions Artifact table",
|
|
||||||
"Reduce commit status",
|
|
||||||
"Add action_tasks_version table",
|
|
||||||
"Update Action Ref",
|
|
||||||
"Drop deleted branch table",
|
|
||||||
"Fix PackageProperty typo",
|
|
||||||
"Allow archiving labels",
|
|
||||||
"Add Version to ActionRun table",
|
|
||||||
"Add Action Schedule Table",
|
|
||||||
"Add Actions artifacts expiration date",
|
|
||||||
"Add ScheduleID for ActionRun",
|
|
||||||
"Add RemoteAddress to mirrors",
|
|
||||||
"Add Index to issue_user.issue_id",
|
|
||||||
"Add Index to comment.dependent_issue_id",
|
|
||||||
"Add Index to action.user_id",
|
|
||||||
"Rename user themes",
|
|
||||||
"Add auth_token table",
|
|
||||||
"Add Index to pull_auto_merge.doer_id",
|
|
||||||
"Add combined Index to issue_user.uid and issue_id",
|
|
||||||
"Add ignore stale approval column on branch table",
|
|
||||||
"Add PreviousDuration to ActionRun",
|
|
||||||
"Add support for SHA256 git repositories",
|
|
||||||
"Use Slug instead of ID for Badges",
|
|
||||||
"Add user_blocking table",
|
|
||||||
"Add default_wiki_branch to repository table",
|
|
||||||
"Add PayloadVersion to HookTask",
|
|
||||||
"Add Index to attachment.comment_id",
|
|
||||||
"Ensure every project has exactly one default column - No Op",
|
|
||||||
"Ensure every project has exactly one default column",
|
|
||||||
"Add unique index for project issue table",
|
|
||||||
"Add commit status summary table",
|
|
||||||
"Add missing field of commit status summary table",
|
|
||||||
"Add everyone_access_mode for repo_unit",
|
|
||||||
"Drop wrongly created table o_auth2_application",
|
|
||||||
"Add content version to issue and comment table",
|
|
||||||
"Add force-push branch protection support",
|
|
||||||
"Add skip_secondary_authorization option to oauth2 application table",
|
|
||||||
"Add metadata column for comment table",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version describes the version table. Should have only one row with id==1
|
|
||||||
type Version struct {
|
|
||||||
ID int64 `xorm:"pk autoincr"`
|
|
||||||
Version int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func MigrateToXormigrate(x *xorm.Engine) error {
|
|
||||||
if err := x.Sync(new(Version)); err != nil {
|
|
||||||
return fmt.Errorf("sync: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
currentVersion := &Version{ID: 1}
|
|
||||||
has, err := x.Get(currentVersion)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get: %w", err)
|
|
||||||
} else if !has {
|
|
||||||
// This should not happen
|
|
||||||
return fmt.Errorf("could not get version")
|
|
||||||
}
|
|
||||||
|
|
||||||
v := currentVersion.Version
|
|
||||||
if minDBVersion > v {
|
|
||||||
log.Fatal(`Gitea no longer supports auto-migration from your previously installed version.
|
|
||||||
Please try upgrading to a lower version first (suggested v1.6.4), then upgrade to this version.`)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Downgrading Gitea's database version not supported
|
|
||||||
if int(v-minDBVersion) > oldMigrationsCount {
|
|
||||||
msg := fmt.Sprintf("Your database (migration version: %d) is for a newer Gitea, you can not use the newer database for this old Gitea release (%d).", v, expectedVersion)
|
|
||||||
msg += "\nGitea will exit to keep your database safe and unchanged. Please use the correct Gitea release, do not change the migration version manually (incorrect manual operation may lose data)."
|
|
||||||
if !setting.IsProd {
|
|
||||||
msg += fmt.Sprintf("\nIf you are in development and really know what you're doing, you can force changing the migration version by executing: UPDATE version SET version=%d WHERE id=1;", expectedVersion)
|
|
||||||
}
|
|
||||||
log.Fatal("Migration Error: %s", msg)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// add migrations that already have been run
|
|
||||||
for _, i := range oldMigrationNames[:v-minDBVersion] {
|
|
||||||
if _, err := x.Insert(&xormigrate.Migration{ID: i}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove old version table
|
|
||||||
return x.DropTables(new(Version))
|
|
||||||
}
|
}
|
||||||
|
305
models/migrations/v1_23/v305.go
Normal file
305
models/migrations/v1_23/v305.go
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package v1_23 //nolint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
|
"src.techknowlogick.com/xormigrate"
|
||||||
|
"xorm.io/xorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
minDBVersion = 70 // Gitea 1.5.3
|
||||||
|
oldMigrationsCount = 230
|
||||||
|
expectedVersion = minDBVersion + oldMigrationsCount
|
||||||
|
)
|
||||||
|
|
||||||
|
var oldMigrationNames = []string{
|
||||||
|
"add issue_dependencies",
|
||||||
|
"protect each scratch token",
|
||||||
|
"add review",
|
||||||
|
"add must_change_password column for users table",
|
||||||
|
"add approval whitelists to protected branches",
|
||||||
|
"clear nonused data which not deleted when user was deleted",
|
||||||
|
"add pull request rebase with merge commit",
|
||||||
|
"add theme to users",
|
||||||
|
"rename repo is_bare to repo is_empty",
|
||||||
|
"add can close issues via commit in any branch",
|
||||||
|
"add is locked to issues",
|
||||||
|
"update U2F counter type",
|
||||||
|
"hot fix for wrong release sha1 on release table",
|
||||||
|
"add uploader id for table attachment",
|
||||||
|
"add table to store original imported gpg keys",
|
||||||
|
"hash application token",
|
||||||
|
"add http method to webhook",
|
||||||
|
"add avatar field to repository",
|
||||||
|
"add commit status context field to commit_status",
|
||||||
|
"add original author/url migration info to issues, comments, and repo ",
|
||||||
|
"change length of some repository columns",
|
||||||
|
"add index on owner_id of repository and type, review_id of comment",
|
||||||
|
"remove orphaned repository index statuses",
|
||||||
|
"add email notification enabled preference to user",
|
||||||
|
"add enable_status_check, status_check_contexts to protected_branch",
|
||||||
|
"add table columns for cross referencing issues",
|
||||||
|
"delete orphaned attachments",
|
||||||
|
"add repo_admin_change_team_access to user",
|
||||||
|
"add original author name and id on migrated release",
|
||||||
|
"add task table and status column for repository table",
|
||||||
|
"update migration repositories' service type",
|
||||||
|
"change length of some external login users columns",
|
||||||
|
"update migration repositories' service type v2",
|
||||||
|
"Add WhitelistDeployKeys to protected branch",
|
||||||
|
"remove unnecessary columns from label",
|
||||||
|
"add includes_all_repositories to teams",
|
||||||
|
"add column `mode` to table watch",
|
||||||
|
"Add template options to repository",
|
||||||
|
"Add comment_id on table notification",
|
||||||
|
"add can_create_org_repo to team",
|
||||||
|
"change review content type to text",
|
||||||
|
"update branch protection for can push and whitelist enable",
|
||||||
|
"remove release attachments which repository deleted",
|
||||||
|
"new feature: change target branch of pull requests",
|
||||||
|
"Remove authentication credentials from stored URL",
|
||||||
|
"add user_id prefix to existing user avatar name",
|
||||||
|
"Extend TrackedTimes",
|
||||||
|
"Add block on rejected reviews branch protection",
|
||||||
|
"Add commit id and stale to reviews",
|
||||||
|
"Fix migrated repositories' git service type",
|
||||||
|
"Add owner_name on table repository",
|
||||||
|
"add is_restricted column for users table",
|
||||||
|
"Add Require Signed Commits to ProtectedBranch",
|
||||||
|
"Add original information for reactions",
|
||||||
|
"Add columns to user and repository",
|
||||||
|
"Add some columns on review for migration",
|
||||||
|
"Fix topic repository count",
|
||||||
|
"add repository code language statistics",
|
||||||
|
"fix merge base for pull requests",
|
||||||
|
"remove dependencies from deleted repositories",
|
||||||
|
"Expand webhooks for more granularity",
|
||||||
|
"Add IsSystemWebhook column to webhooks table",
|
||||||
|
"Add Branch Protection Protected Files Column",
|
||||||
|
"Add EmailHash Table",
|
||||||
|
"Refix merge base for merged pull requests",
|
||||||
|
"Add OrgID column to Labels table",
|
||||||
|
"Add CommitsAhead and CommitsBehind Column to PullRequest Table",
|
||||||
|
"Add Branch Protection Block Outdated Branch",
|
||||||
|
"Add ResolveDoerID to Comment table",
|
||||||
|
"prepend refs/heads/ to issue refs",
|
||||||
|
"Save detected language file size to database instead of percent",
|
||||||
|
"Add KeepActivityPrivate to User table",
|
||||||
|
"Ensure Repository.IsArchived is not null",
|
||||||
|
"recalculate Stars number for all user",
|
||||||
|
"update Matrix Webhook http method to 'PUT'",
|
||||||
|
"Increase Language field to 50 in LanguageStats",
|
||||||
|
"Add projects info to repository table",
|
||||||
|
"create review for 0 review id code comments",
|
||||||
|
"remove issue dependency comments who refer to non existing issues",
|
||||||
|
"Add Created and Updated to Milestone table",
|
||||||
|
"add primary key to repo_topic",
|
||||||
|
"set default password algorithm to Argon2",
|
||||||
|
"add TrustModel field to Repository",
|
||||||
|
"add Team review request support",
|
||||||
|
"add timestamps to Star, Label, Follow, Watch and Collaboration",
|
||||||
|
"add changed_protected_files column for pull_request table",
|
||||||
|
"fix publisher ID for tag releases",
|
||||||
|
"ensure repo topics are up-to-date",
|
||||||
|
"code comment replies should have the commitID of the review they are replying to",
|
||||||
|
"update reactions constraint",
|
||||||
|
"Add block on official review requests branch protection",
|
||||||
|
"Convert task type from int to string",
|
||||||
|
"Convert webhook task type from int to string",
|
||||||
|
"Convert topic name from 25 to 50",
|
||||||
|
"Add scope and nonce columns to oauth2_grant table",
|
||||||
|
"Convert hook task type from char(16) to varchar(16) and trim the column",
|
||||||
|
"Where Password is Valid with Empty String delete it",
|
||||||
|
"Add user redirect",
|
||||||
|
"Recreate user table to fix default values",
|
||||||
|
"Update DeleteBranch comments to set the old_ref to the commit_sha",
|
||||||
|
"Add Dismissed to Review table",
|
||||||
|
"Add Sorting to ProjectBoard table",
|
||||||
|
"Add sessions table for go-chi/session",
|
||||||
|
"Add time_id column to Comment",
|
||||||
|
"Create repo transfer table",
|
||||||
|
"Fix Postgres ID Sequences broken by recreate-table",
|
||||||
|
"Remove invalid labels from comments",
|
||||||
|
"Delete orphaned IssueLabels",
|
||||||
|
"Add LFS columns to Mirror",
|
||||||
|
"Convert avatar url to text",
|
||||||
|
"Delete credentials from past migrations",
|
||||||
|
"Always save primary email on email address table",
|
||||||
|
"Add issue resource index table",
|
||||||
|
"Create PushMirror table",
|
||||||
|
"Rename Task errors to message",
|
||||||
|
"Add new table repo_archiver",
|
||||||
|
"Create protected tag table",
|
||||||
|
"Drop unneeded webhook related columns",
|
||||||
|
"Add key is verified to gpg key",
|
||||||
|
"Unwrap ldap.Sources",
|
||||||
|
"Add agit flow pull request support",
|
||||||
|
"Alter issue/comment table TEXT fields to LONGTEXT",
|
||||||
|
"RecreateIssueResourceIndexTable to have a primary key instead of an unique index",
|
||||||
|
"Add repo id column for attachment table",
|
||||||
|
"Add Branch Protection Unprotected Files Column",
|
||||||
|
"Add table commit_status_index",
|
||||||
|
"Add Color to ProjectBoard table",
|
||||||
|
"Add renamed_branch table",
|
||||||
|
"Add issue content history table",
|
||||||
|
"No-op (remote version is using AppState now)",
|
||||||
|
"Add table app_state",
|
||||||
|
"Drop table remote_version (if exists)",
|
||||||
|
"Create key/value table for user settings",
|
||||||
|
"Add Sorting to ProjectIssue table",
|
||||||
|
"Add key is verified to ssh key",
|
||||||
|
"Migrate to higher varchar on user struct",
|
||||||
|
"Add authorize column to team_unit table",
|
||||||
|
"Add webauthn table and migrate u2f data to webauthn - NO-OPED",
|
||||||
|
"Use base32.HexEncoding instead of base64 encoding for cred ID as it is case insensitive - NO-OPED",
|
||||||
|
"Increase WebAuthentication CredentialID size to 410 - NO-OPED",
|
||||||
|
"v208 was completely broken - remigrate",
|
||||||
|
"Create ForeignReference table",
|
||||||
|
"Add package tables",
|
||||||
|
"Add allow edits from maintainers to PullRequest table",
|
||||||
|
"Add auto merge table",
|
||||||
|
"allow to view files in PRs",
|
||||||
|
"No-op (Improve Action table indices v1)",
|
||||||
|
"Alter hook_task table TEXT fields to LONGTEXT",
|
||||||
|
"Improve Action table indices v2",
|
||||||
|
"Add sync_on_commit column to push_mirror table",
|
||||||
|
"Add container repository property",
|
||||||
|
"Store WebAuthentication CredentialID as bytes and increase size to at least 1024",
|
||||||
|
"Drop old CredentialID column",
|
||||||
|
"Rename CredentialIDBytes column to CredentialID",
|
||||||
|
"Add badges to users",
|
||||||
|
"Alter gpg_key/public_key content TEXT fields to MEDIUMTEXT",
|
||||||
|
"Conan and generic packages do not need to be semantically versioned",
|
||||||
|
"Create key/value table for system settings",
|
||||||
|
"Add TeamInvite table",
|
||||||
|
"Update counts of all open milestones",
|
||||||
|
"Add ConfidentialClient column (default true) to OAuth2Application table",
|
||||||
|
"Add index for hook_task",
|
||||||
|
"Alter package_version.metadata_json to LONGTEXT",
|
||||||
|
"Add header_authorization_encrypted column to webhook table",
|
||||||
|
"Add package cleanup rule table",
|
||||||
|
"Add index for access_token",
|
||||||
|
"Create secrets table",
|
||||||
|
"Drop ForeignReference table",
|
||||||
|
"Add updated unix to LFSMetaObject",
|
||||||
|
"Add scope for access_token",
|
||||||
|
"Add actions tables",
|
||||||
|
"Add card_type column to project table",
|
||||||
|
"Alter gpg_key_import content TEXT field to MEDIUMTEXT",
|
||||||
|
"Add exclusive label",
|
||||||
|
"Add NeedApproval to actions tables",
|
||||||
|
"Rename Webhook org_id to owner_id",
|
||||||
|
"Add missed column owner_id for project table",
|
||||||
|
"Fix incorrect project type",
|
||||||
|
"Add version column to action_runner table",
|
||||||
|
"Improve Action table indices v3",
|
||||||
|
"Change Container Metadata",
|
||||||
|
"Fix incorrect owner team unit access mode",
|
||||||
|
"Fix incorrect admin team unit access mode",
|
||||||
|
"Fix ExternalTracker and ExternalWiki accessMode in owner and admin team",
|
||||||
|
"Add ActionTaskOutput table",
|
||||||
|
"Add ArchivedUnix Column",
|
||||||
|
"Add is_internal column to package",
|
||||||
|
"Add Actions Artifact table",
|
||||||
|
"Add PinOrder Column",
|
||||||
|
"Convert scoped access tokens",
|
||||||
|
"Drop custom_labels column of action_runner table",
|
||||||
|
"Add variable table",
|
||||||
|
"Add TriggerEvent to action_run table",
|
||||||
|
"Add git_size and lfs_size columns to repository table",
|
||||||
|
"Add branch table",
|
||||||
|
"Alter Actions Artifact table",
|
||||||
|
"Reduce commit status",
|
||||||
|
"Add action_tasks_version table",
|
||||||
|
"Update Action Ref",
|
||||||
|
"Drop deleted branch table",
|
||||||
|
"Fix PackageProperty typo",
|
||||||
|
"Allow archiving labels",
|
||||||
|
"Add Version to ActionRun table",
|
||||||
|
"Add Action Schedule Table",
|
||||||
|
"Add Actions artifacts expiration date",
|
||||||
|
"Add ScheduleID for ActionRun",
|
||||||
|
"Add RemoteAddress to mirrors",
|
||||||
|
"Add Index to issue_user.issue_id",
|
||||||
|
"Add Index to comment.dependent_issue_id",
|
||||||
|
"Add Index to action.user_id",
|
||||||
|
"Rename user themes",
|
||||||
|
"Add auth_token table",
|
||||||
|
"Add Index to pull_auto_merge.doer_id",
|
||||||
|
"Add combined Index to issue_user.uid and issue_id",
|
||||||
|
"Add ignore stale approval column on branch table",
|
||||||
|
"Add PreviousDuration to ActionRun",
|
||||||
|
"Add support for SHA256 git repositories",
|
||||||
|
"Use Slug instead of ID for Badges",
|
||||||
|
"Add user_blocking table",
|
||||||
|
"Add default_wiki_branch to repository table",
|
||||||
|
"Add PayloadVersion to HookTask",
|
||||||
|
"Add Index to attachment.comment_id",
|
||||||
|
"Ensure every project has exactly one default column - No Op",
|
||||||
|
"Ensure every project has exactly one default column",
|
||||||
|
"Add unique index for project issue table",
|
||||||
|
"Add commit status summary table",
|
||||||
|
"Add missing field of commit status summary table",
|
||||||
|
"Add everyone_access_mode for repo_unit",
|
||||||
|
"Drop wrongly created table o_auth2_application",
|
||||||
|
"Add content version to issue and comment table",
|
||||||
|
"Add force-push branch protection support",
|
||||||
|
"Add skip_secondary_authorization option to oauth2 application table",
|
||||||
|
"Add metadata column for comment table",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version describes the version table. Should have only one row with id==1
|
||||||
|
type Version struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
Version int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func MigrateToXormigrate(x *xorm.Engine) error {
|
||||||
|
if err := x.Sync(new(Version)); err != nil {
|
||||||
|
return fmt.Errorf("sync: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
currentVersion := &Version{ID: 1}
|
||||||
|
has, err := x.Get(currentVersion)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("get: %w", err)
|
||||||
|
} else if !has {
|
||||||
|
// This should not happen
|
||||||
|
return fmt.Errorf("could not get version")
|
||||||
|
}
|
||||||
|
|
||||||
|
v := currentVersion.Version
|
||||||
|
if minDBVersion > v {
|
||||||
|
log.Fatal(`Gitea no longer supports auto-migration from your previously installed version.
|
||||||
|
Please try upgrading to a lower version first (suggested v1.6.4), then upgrade to this version.`)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Downgrading Gitea's database version not supported
|
||||||
|
if int(v-minDBVersion) > oldMigrationsCount {
|
||||||
|
msg := fmt.Sprintf("Your database (migration version: %d) is for a newer Gitea, you can not use the newer database for this old Gitea release (%d).", v, expectedVersion)
|
||||||
|
msg += "\nGitea will exit to keep your database safe and unchanged. Please use the correct Gitea release, do not change the migration version manually (incorrect manual operation may lose data)."
|
||||||
|
if !setting.IsProd {
|
||||||
|
msg += fmt.Sprintf("\nIf you are in development and really know what you're doing, you can force changing the migration version by executing: UPDATE version SET version=%d WHERE id=1;", expectedVersion)
|
||||||
|
}
|
||||||
|
log.Fatal("Migration Error: %s", msg)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// add migrations that already have been run
|
||||||
|
for _, i := range oldMigrationNames[:v-minDBVersion] {
|
||||||
|
if _, err := x.Insert(&xormigrate.Migration{ID: i}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove old version table
|
||||||
|
return x.DropTables(new(Version))
|
||||||
|
}
|
@ -77,7 +77,7 @@ type Release struct {
|
|||||||
Target string
|
Target string
|
||||||
TargetBehind string `xorm:"-"` // to handle non-existing or empty target
|
TargetBehind string `xorm:"-"` // to handle non-existing or empty target
|
||||||
Title string
|
Title string
|
||||||
Sha1 string `xorm:"VARCHAR(64)"`
|
Sha1 string `xorm:"INDEX VARCHAR(64)"`
|
||||||
NumCommits int64
|
NumCommits int64
|
||||||
NumCommitsBehind int64 `xorm:"-"`
|
NumCommitsBehind int64 `xorm:"-"`
|
||||||
Note string `xorm:"TEXT"`
|
Note string `xorm:"TEXT"`
|
||||||
@ -537,3 +537,17 @@ func InsertReleases(ctx context.Context, rels ...*Release) error {
|
|||||||
|
|
||||||
return committer.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FindTagsByCommitIDs(ctx context.Context, repoID int64, commitIDs ...string) (map[string][]*Release, error) {
|
||||||
|
releases := make([]*Release, 0, len(commitIDs))
|
||||||
|
if err := db.GetEngine(ctx).Where("repo_id=?", repoID).
|
||||||
|
In("sha1", commitIDs).
|
||||||
|
Find(&releases); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res := make(map[string][]*Release, len(releases))
|
||||||
|
for _, r := range releases {
|
||||||
|
res[r.Sha1] = append(res[r.Sha1], r)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
@ -25,3 +25,16 @@ func TestMigrate_InsertReleases(t *testing.T) {
|
|||||||
err := InsertReleases(db.DefaultContext, r)
|
err := InsertReleases(db.DefaultContext, r)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_FindTagsByCommitIDs(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
sha1Rels, err := FindTagsByCommitIDs(db.DefaultContext, 1, "65f1bf27bc3bf70f64657658635e66094edbcb4d")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, sha1Rels, 1)
|
||||||
|
rels := sha1Rels["65f1bf27bc3bf70f64657658635e66094edbcb4d"]
|
||||||
|
assert.Len(t, rels, 3)
|
||||||
|
assert.Equal(t, "v1.1", rels[0].TagName)
|
||||||
|
assert.Equal(t, "delete-tag", rels[1].TagName)
|
||||||
|
assert.Equal(t, "v1.0", rels[2].TagName)
|
||||||
|
}
|
||||||
|
46
modules/git/batch.go
Normal file
46
modules/git/batch.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package git
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Batch struct {
|
||||||
|
cancel context.CancelFunc
|
||||||
|
Reader *bufio.Reader
|
||||||
|
Writer WriteCloserError
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *Repository) NewBatch(ctx context.Context) (*Batch, error) {
|
||||||
|
// Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
|
||||||
|
if err := ensureValidGitRepository(ctx, repo.Path); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var batch Batch
|
||||||
|
batch.Writer, batch.Reader, batch.cancel = catFileBatch(ctx, repo.Path)
|
||||||
|
return &batch, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *Repository) NewBatchCheck(ctx context.Context) (*Batch, error) {
|
||||||
|
// Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
|
||||||
|
if err := ensureValidGitRepository(ctx, repo.Path); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var check Batch
|
||||||
|
check.Writer, check.Reader, check.cancel = catFileBatchCheck(ctx, repo.Path)
|
||||||
|
return &check, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Batch) Close() {
|
||||||
|
if b.cancel != nil {
|
||||||
|
b.cancel()
|
||||||
|
b.Reader = nil
|
||||||
|
b.Writer = nil
|
||||||
|
b.cancel = nil
|
||||||
|
}
|
||||||
|
}
|
@ -26,10 +26,10 @@ type WriteCloserError interface {
|
|||||||
CloseWithError(err error) error
|
CloseWithError(err error) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnsureValidGitRepository runs git rev-parse in the repository path - thus ensuring that the repository is a valid repository.
|
// ensureValidGitRepository runs git rev-parse in the repository path - thus ensuring that the repository is a valid repository.
|
||||||
// Run before opening git cat-file.
|
// Run before opening git cat-file.
|
||||||
// This is needed otherwise the git cat-file will hang for invalid repositories.
|
// This is needed otherwise the git cat-file will hang for invalid repositories.
|
||||||
func EnsureValidGitRepository(ctx context.Context, repoPath string) error {
|
func ensureValidGitRepository(ctx context.Context, repoPath string) error {
|
||||||
stderr := strings.Builder{}
|
stderr := strings.Builder{}
|
||||||
err := NewCommand(ctx, "rev-parse").
|
err := NewCommand(ctx, "rev-parse").
|
||||||
SetDescription(fmt.Sprintf("%s rev-parse [repo_path: %s]", GitExecutable, repoPath)).
|
SetDescription(fmt.Sprintf("%s rev-parse [repo_path: %s]", GitExecutable, repoPath)).
|
||||||
@ -43,8 +43,8 @@ func EnsureValidGitRepository(ctx context.Context, repoPath string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CatFileBatchCheck opens git cat-file --batch-check in the provided repo and returns a stdin pipe, a stdout reader and cancel function
|
// catFileBatchCheck opens git cat-file --batch-check in the provided repo and returns a stdin pipe, a stdout reader and cancel function
|
||||||
func CatFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError, *bufio.Reader, func()) {
|
func catFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError, *bufio.Reader, func()) {
|
||||||
batchStdinReader, batchStdinWriter := io.Pipe()
|
batchStdinReader, batchStdinWriter := io.Pipe()
|
||||||
batchStdoutReader, batchStdoutWriter := io.Pipe()
|
batchStdoutReader, batchStdoutWriter := io.Pipe()
|
||||||
ctx, ctxCancel := context.WithCancel(ctx)
|
ctx, ctxCancel := context.WithCancel(ctx)
|
||||||
@ -93,8 +93,8 @@ func CatFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError,
|
|||||||
return batchStdinWriter, batchReader, cancel
|
return batchStdinWriter, batchReader, cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
// CatFileBatch opens git cat-file --batch in the provided repo and returns a stdin pipe, a stdout reader and cancel function
|
// catFileBatch opens git cat-file --batch in the provided repo and returns a stdin pipe, a stdout reader and cancel function
|
||||||
func CatFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufio.Reader, func()) {
|
func catFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufio.Reader, func()) {
|
||||||
// We often want to feed the commits in order into cat-file --batch, followed by their trees and sub trees as necessary.
|
// We often want to feed the commits in order into cat-file --batch, followed by their trees and sub trees as necessary.
|
||||||
// so let's create a batch stdin and stdout
|
// so let's create a batch stdin and stdout
|
||||||
batchStdinReader, batchStdinWriter := io.Pipe()
|
batchStdinReader, batchStdinWriter := io.Pipe()
|
||||||
|
@ -26,9 +26,12 @@ type Blob struct {
|
|||||||
// DataAsync gets a ReadCloser for the contents of a blob without reading it all.
|
// DataAsync gets a ReadCloser for the contents of a blob without reading it all.
|
||||||
// Calling the Close function on the result will discard all unread output.
|
// Calling the Close function on the result will discard all unread output.
|
||||||
func (b *Blob) DataAsync() (io.ReadCloser, error) {
|
func (b *Blob) DataAsync() (io.ReadCloser, error) {
|
||||||
wr, rd, cancel := b.repo.CatFileBatch(b.repo.Ctx)
|
wr, rd, cancel, err := b.repo.CatFileBatch(b.repo.Ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
_, err := wr.Write([]byte(b.ID.String() + "\n"))
|
_, err = wr.Write([]byte(b.ID.String() + "\n"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cancel()
|
cancel()
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -64,9 +67,13 @@ func (b *Blob) Size() int64 {
|
|||||||
return b.size
|
return b.size
|
||||||
}
|
}
|
||||||
|
|
||||||
wr, rd, cancel := b.repo.CatFileBatchCheck(b.repo.Ctx)
|
wr, rd, cancel, err := b.repo.CatFileBatchCheck(b.repo.Ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("error whilst reading size for %s in %s. Error: %v", b.ID.String(), b.repo.Path, err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
_, err := wr.Write([]byte(b.ID.String() + "\n"))
|
_, err = wr.Write([]byte(b.ID.String() + "\n"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("error whilst reading size for %s in %s. Error: %v", b.ID.String(), b.repo.Path, err)
|
log.Debug("error whilst reading size for %s in %s. Error: %v", b.ID.String(), b.repo.Path, err)
|
||||||
return 0
|
return 0
|
||||||
|
@ -124,7 +124,10 @@ func GetLastCommitForPaths(ctx context.Context, commit *Commit, treePath string,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
batchStdinWriter, batchReader, cancel := commit.repo.CatFileBatch(ctx)
|
batchStdinWriter, batchReader, cancel, err := commit.repo.CatFileBatch(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
commitsMap := map[string]*Commit{}
|
commitsMap := map[string]*Commit{}
|
||||||
|
@ -46,7 +46,10 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
|
|||||||
|
|
||||||
// Next feed the commits in order into cat-file --batch, followed by their trees and sub trees as necessary.
|
// Next feed the commits in order into cat-file --batch, followed by their trees and sub trees as necessary.
|
||||||
// so let's create a batch stdin and stdout
|
// so let's create a batch stdin and stdout
|
||||||
batchStdinWriter, batchReader, cancel := repo.CatFileBatch(repo.Ctx)
|
batchStdinWriter, batchReader, cancel, err := repo.CatFileBatch(repo.Ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// We'll use a scanner for the revList because it's simpler than a bufio.Reader
|
// We'll use a scanner for the revList because it's simpler than a bufio.Reader
|
||||||
|
@ -25,15 +25,11 @@ type Repository struct {
|
|||||||
|
|
||||||
gpgSettings *GPGSettings
|
gpgSettings *GPGSettings
|
||||||
|
|
||||||
batchInUse bool
|
batchInUse bool
|
||||||
batchCancel context.CancelFunc
|
batch *Batch
|
||||||
batchReader *bufio.Reader
|
|
||||||
batchWriter WriteCloserError
|
|
||||||
|
|
||||||
checkInUse bool
|
checkInUse bool
|
||||||
checkCancel context.CancelFunc
|
check *Batch
|
||||||
checkReader *bufio.Reader
|
|
||||||
checkWriter WriteCloserError
|
|
||||||
|
|
||||||
Ctx context.Context
|
Ctx context.Context
|
||||||
LastCommitCache *LastCommitCache
|
LastCommitCache *LastCommitCache
|
||||||
@ -55,63 +51,75 @@ func OpenRepository(ctx context.Context, repoPath string) (*Repository, error) {
|
|||||||
return nil, util.NewNotExistErrorf("no such file or directory")
|
return nil, util.NewNotExistErrorf("no such file or directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
|
return &Repository{
|
||||||
if err := EnsureValidGitRepository(ctx, repoPath); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
repo := &Repository{
|
|
||||||
Path: repoPath,
|
Path: repoPath,
|
||||||
tagCache: newObjectCache(),
|
tagCache: newObjectCache(),
|
||||||
Ctx: ctx,
|
Ctx: ctx,
|
||||||
}
|
}, nil
|
||||||
|
|
||||||
repo.batchWriter, repo.batchReader, repo.batchCancel = CatFileBatch(ctx, repoPath)
|
|
||||||
repo.checkWriter, repo.checkReader, repo.checkCancel = CatFileBatchCheck(ctx, repoPath)
|
|
||||||
|
|
||||||
return repo, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CatFileBatch obtains a CatFileBatch for this repository
|
// CatFileBatch obtains a CatFileBatch for this repository
|
||||||
func (repo *Repository) CatFileBatch(ctx context.Context) (WriteCloserError, *bufio.Reader, func()) {
|
func (repo *Repository) CatFileBatch(ctx context.Context) (WriteCloserError, *bufio.Reader, func(), error) {
|
||||||
if repo.batchCancel == nil || repo.batchInUse {
|
if repo.batch == nil {
|
||||||
log.Debug("Opening temporary cat file batch for: %s", repo.Path)
|
var err error
|
||||||
return CatFileBatch(ctx, repo.Path)
|
repo.batch, err = repo.NewBatch(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
repo.batchInUse = true
|
|
||||||
return repo.batchWriter, repo.batchReader, func() {
|
if !repo.batchInUse {
|
||||||
repo.batchInUse = false
|
repo.batchInUse = true
|
||||||
|
return repo.batch.Writer, repo.batch.Reader, func() {
|
||||||
|
repo.batchInUse = false
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debug("Opening temporary cat file batch for: %s", repo.Path)
|
||||||
|
tempBatch, err := repo.NewBatch(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
return tempBatch.Writer, tempBatch.Reader, tempBatch.Close, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CatFileBatchCheck obtains a CatFileBatchCheck for this repository
|
// CatFileBatchCheck obtains a CatFileBatchCheck for this repository
|
||||||
func (repo *Repository) CatFileBatchCheck(ctx context.Context) (WriteCloserError, *bufio.Reader, func()) {
|
func (repo *Repository) CatFileBatchCheck(ctx context.Context) (WriteCloserError, *bufio.Reader, func(), error) {
|
||||||
if repo.checkCancel == nil || repo.checkInUse {
|
if repo.check == nil {
|
||||||
log.Debug("Opening temporary cat file batch-check for: %s", repo.Path)
|
var err error
|
||||||
return CatFileBatchCheck(ctx, repo.Path)
|
repo.check, err = repo.NewBatchCheck(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
repo.checkInUse = true
|
|
||||||
return repo.checkWriter, repo.checkReader, func() {
|
if !repo.checkInUse {
|
||||||
repo.checkInUse = false
|
repo.checkInUse = true
|
||||||
|
return repo.check.Writer, repo.check.Reader, func() {
|
||||||
|
repo.checkInUse = false
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debug("Opening temporary cat file batch-check for: %s", repo.Path)
|
||||||
|
tempBatchCheck, err := repo.NewBatchCheck(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
return tempBatchCheck.Writer, tempBatchCheck.Reader, tempBatchCheck.Close, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Repository) Close() error {
|
func (repo *Repository) Close() error {
|
||||||
if repo == nil {
|
if repo == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if repo.batchCancel != nil {
|
if repo.batch != nil {
|
||||||
repo.batchCancel()
|
repo.batch.Close()
|
||||||
repo.batchReader = nil
|
repo.batch = nil
|
||||||
repo.batchWriter = nil
|
|
||||||
repo.batchCancel = nil
|
|
||||||
repo.batchInUse = false
|
repo.batchInUse = false
|
||||||
}
|
}
|
||||||
if repo.checkCancel != nil {
|
if repo.check != nil {
|
||||||
repo.checkCancel()
|
repo.check.Close()
|
||||||
repo.checkCancel = nil
|
repo.check = nil
|
||||||
repo.checkReader = nil
|
|
||||||
repo.checkWriter = nil
|
|
||||||
repo.checkInUse = false
|
repo.checkInUse = false
|
||||||
}
|
}
|
||||||
repo.LastCommitCache = nil
|
repo.LastCommitCache = nil
|
||||||
|
@ -22,9 +22,13 @@ func (repo *Repository) IsObjectExist(name string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
|
wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Error writing to CatFileBatchCheck %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
_, err := wr.Write([]byte(name + "\n"))
|
_, err = wr.Write([]byte(name + "\n"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Error writing to CatFileBatchCheck %v", err)
|
log.Debug("Error writing to CatFileBatchCheck %v", err)
|
||||||
return false
|
return false
|
||||||
@ -39,9 +43,13 @@ func (repo *Repository) IsReferenceExist(name string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
|
wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Error writing to CatFileBatchCheck %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
_, err := wr.Write([]byte(name + "\n"))
|
_, err = wr.Write([]byte(name + "\n"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Error writing to CatFileBatchCheck %v", err)
|
log.Debug("Error writing to CatFileBatchCheck %v", err)
|
||||||
return false
|
return false
|
||||||
|
@ -33,9 +33,12 @@ func (repo *Repository) ResolveReference(name string) (string, error) {
|
|||||||
|
|
||||||
// GetRefCommitID returns the last commit ID string of given reference (branch or tag).
|
// GetRefCommitID returns the last commit ID string of given reference (branch or tag).
|
||||||
func (repo *Repository) GetRefCommitID(name string) (string, error) {
|
func (repo *Repository) GetRefCommitID(name string) (string, error) {
|
||||||
wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
|
wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
_, err := wr.Write([]byte(name + "\n"))
|
_, err = wr.Write([]byte(name + "\n"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -61,12 +64,19 @@ func (repo *Repository) RemoveReference(name string) error {
|
|||||||
|
|
||||||
// IsCommitExist returns true if given commit exists in current repository.
|
// IsCommitExist returns true if given commit exists in current repository.
|
||||||
func (repo *Repository) IsCommitExist(name string) bool {
|
func (repo *Repository) IsCommitExist(name string) bool {
|
||||||
|
if err := ensureValidGitRepository(repo.Ctx, repo.Path); err != nil {
|
||||||
|
log.Error("IsCommitExist: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
_, _, err := NewCommand(repo.Ctx, "cat-file", "-e").AddDynamicArguments(name).RunStdString(&RunOpts{Dir: repo.Path})
|
_, _, err := NewCommand(repo.Ctx, "cat-file", "-e").AddDynamicArguments(name).RunStdString(&RunOpts{Dir: repo.Path})
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Repository) getCommit(id ObjectID) (*Commit, error) {
|
func (repo *Repository) getCommit(id ObjectID) (*Commit, error) {
|
||||||
wr, rd, cancel := repo.CatFileBatch(repo.Ctx)
|
wr, rd, cancel, err := repo.CatFileBatch(repo.Ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
_, _ = wr.Write([]byte(id.String() + "\n"))
|
_, _ = wr.Write([]byte(id.String() + "\n"))
|
||||||
@ -143,7 +153,10 @@ func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
|
wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
_, err = wr.Write([]byte(commitID + "\n"))
|
_, err = wr.Write([]byte(commitID + "\n"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -20,7 +20,10 @@ import (
|
|||||||
func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, error) {
|
func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, error) {
|
||||||
// We will feed the commit IDs in order into cat-file --batch, followed by blobs as necessary.
|
// We will feed the commit IDs in order into cat-file --batch, followed by blobs as necessary.
|
||||||
// so let's create a batch stdin and stdout
|
// so let's create a batch stdin and stdout
|
||||||
batchStdinWriter, batchReader, cancel := repo.CatFileBatch(repo.Ctx)
|
batchStdinWriter, batchReader, cancel, err := repo.CatFileBatch(repo.Ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
writeID := func(id string) error {
|
writeID := func(id string) error {
|
||||||
|
@ -31,9 +31,12 @@ func (repo *Repository) GetTags(skip, limit int) (tags []string, err error) {
|
|||||||
|
|
||||||
// GetTagType gets the type of the tag, either commit (simple) or tag (annotated)
|
// GetTagType gets the type of the tag, either commit (simple) or tag (annotated)
|
||||||
func (repo *Repository) GetTagType(id ObjectID) (string, error) {
|
func (repo *Repository) GetTagType(id ObjectID) (string, error) {
|
||||||
wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
|
wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
_, err := wr.Write([]byte(id.String() + "\n"))
|
_, err = wr.Write([]byte(id.String() + "\n"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -89,7 +92,10 @@ func (repo *Repository) getTag(tagID ObjectID, name string) (*Tag, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The tag is an annotated tag with a message.
|
// The tag is an annotated tag with a message.
|
||||||
wr, rd, cancel := repo.CatFileBatch(repo.Ctx)
|
wr, rd, cancel, err := repo.CatFileBatch(repo.Ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if _, err := wr.Write([]byte(tagID.String() + "\n")); err != nil {
|
if _, err := wr.Write([]byte(tagID.String() + "\n")); err != nil {
|
||||||
|
@ -10,7 +10,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (repo *Repository) getTree(id ObjectID) (*Tree, error) {
|
func (repo *Repository) getTree(id ObjectID) (*Tree, error) {
|
||||||
wr, rd, cancel := repo.CatFileBatch(repo.Ctx)
|
wr, rd, cancel, err := repo.CatFileBatch(repo.Ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
_, _ = wr.Write([]byte(id.String() + "\n"))
|
_, _ = wr.Write([]byte(id.String() + "\n"))
|
||||||
|
@ -42,9 +42,13 @@ func (te *TreeEntry) Size() int64 {
|
|||||||
return te.size
|
return te.size
|
||||||
}
|
}
|
||||||
|
|
||||||
wr, rd, cancel := te.ptree.repo.CatFileBatchCheck(te.ptree.repo.Ctx)
|
wr, rd, cancel, err := te.ptree.repo.CatFileBatchCheck(te.ptree.repo.Ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("error whilst reading size for %s in %s. Error: %v", te.ID.String(), te.ptree.repo.Path, err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
_, err := wr.Write([]byte(te.ID.String() + "\n"))
|
_, err = wr.Write([]byte(te.ID.String() + "\n"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("error whilst reading size for %s in %s. Error: %v", te.ID.String(), te.ptree.repo.Path, err)
|
log.Debug("error whilst reading size for %s in %s. Error: %v", te.ID.String(), te.ptree.repo.Path, err)
|
||||||
return 0
|
return 0
|
||||||
|
@ -33,7 +33,10 @@ func (t *Tree) ListEntries() (Entries, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if t.repo != nil {
|
if t.repo != nil {
|
||||||
wr, rd, cancel := t.repo.CatFileBatch(t.repo.Ctx)
|
wr, rd, cancel, err := t.repo.CatFileBatch(t.repo.Ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
_, _ = wr.Write([]byte(t.ID.String() + "\n"))
|
_, _ = wr.Write([]byte(t.ID.String() + "\n"))
|
||||||
|
@ -16,10 +16,10 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/analyze"
|
"code.gitea.io/gitea/modules/analyze"
|
||||||
"code.gitea.io/gitea/modules/charset"
|
"code.gitea.io/gitea/modules/charset"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
"code.gitea.io/gitea/modules/gitrepo"
|
||||||
"code.gitea.io/gitea/modules/indexer/code/internal"
|
"code.gitea.io/gitea/modules/indexer/code/internal"
|
||||||
indexer_internal "code.gitea.io/gitea/modules/indexer/internal"
|
indexer_internal "code.gitea.io/gitea/modules/indexer/internal"
|
||||||
inner_bleve "code.gitea.io/gitea/modules/indexer/internal/bleve"
|
inner_bleve "code.gitea.io/gitea/modules/indexer/internal/bleve"
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/typesniffer"
|
"code.gitea.io/gitea/modules/typesniffer"
|
||||||
@ -189,21 +189,23 @@ func (b *Indexer) addDelete(filename string, repo *repo_model.Repository, batch
|
|||||||
func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha string, changes *internal.RepoChanges) error {
|
func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha string, changes *internal.RepoChanges) error {
|
||||||
batch := inner_bleve.NewFlushingBatch(b.inner.Indexer, maxBatchSize)
|
batch := inner_bleve.NewFlushingBatch(b.inner.Indexer, maxBatchSize)
|
||||||
if len(changes.Updates) > 0 {
|
if len(changes.Updates) > 0 {
|
||||||
// Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
|
r, err := gitrepo.OpenRepository(ctx, repo)
|
||||||
if err := git.EnsureValidGitRepository(ctx, repo.RepoPath()); err != nil {
|
if err != nil {
|
||||||
log.Error("Unable to open git repo: %s for %-v: %v", repo.RepoPath(), repo, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer r.Close()
|
||||||
batchWriter, batchReader, cancel := git.CatFileBatch(ctx, repo.RepoPath())
|
gitBatch, err := r.NewBatch(ctx)
|
||||||
defer cancel()
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer gitBatch.Close()
|
||||||
|
|
||||||
for _, update := range changes.Updates {
|
for _, update := range changes.Updates {
|
||||||
if err := b.addUpdate(ctx, batchWriter, batchReader, sha, update, repo, batch); err != nil {
|
if err := b.addUpdate(ctx, gitBatch.Writer, gitBatch.Reader, sha, update, repo, batch); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cancel()
|
gitBatch.Close()
|
||||||
}
|
}
|
||||||
for _, filename := range changes.RemovedFilenames {
|
for _, filename := range changes.RemovedFilenames {
|
||||||
if err := b.addDelete(filename, repo, batch); err != nil {
|
if err := b.addDelete(filename, repo, batch); err != nil {
|
||||||
|
@ -15,11 +15,11 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/analyze"
|
"code.gitea.io/gitea/modules/analyze"
|
||||||
"code.gitea.io/gitea/modules/charset"
|
"code.gitea.io/gitea/modules/charset"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
"code.gitea.io/gitea/modules/gitrepo"
|
||||||
"code.gitea.io/gitea/modules/indexer/code/internal"
|
"code.gitea.io/gitea/modules/indexer/code/internal"
|
||||||
indexer_internal "code.gitea.io/gitea/modules/indexer/internal"
|
indexer_internal "code.gitea.io/gitea/modules/indexer/internal"
|
||||||
inner_elasticsearch "code.gitea.io/gitea/modules/indexer/internal/elasticsearch"
|
inner_elasticsearch "code.gitea.io/gitea/modules/indexer/internal/elasticsearch"
|
||||||
"code.gitea.io/gitea/modules/json"
|
"code.gitea.io/gitea/modules/json"
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/typesniffer"
|
"code.gitea.io/gitea/modules/typesniffer"
|
||||||
@ -154,17 +154,19 @@ func (b *Indexer) addDelete(filename string, repo *repo_model.Repository) elasti
|
|||||||
func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha string, changes *internal.RepoChanges) error {
|
func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha string, changes *internal.RepoChanges) error {
|
||||||
reqs := make([]elastic.BulkableRequest, 0)
|
reqs := make([]elastic.BulkableRequest, 0)
|
||||||
if len(changes.Updates) > 0 {
|
if len(changes.Updates) > 0 {
|
||||||
// Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
|
r, err := gitrepo.OpenRepository(ctx, repo)
|
||||||
if err := git.EnsureValidGitRepository(ctx, repo.RepoPath()); err != nil {
|
if err != nil {
|
||||||
log.Error("Unable to open git repo: %s for %-v: %v", repo.RepoPath(), repo, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer r.Close()
|
||||||
batchWriter, batchReader, cancel := git.CatFileBatch(ctx, repo.RepoPath())
|
batch, err := r.NewBatch(ctx)
|
||||||
defer cancel()
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer batch.Close()
|
||||||
|
|
||||||
for _, update := range changes.Updates {
|
for _, update := range changes.Updates {
|
||||||
updateReqs, err := b.addUpdate(ctx, batchWriter, batchReader, sha, update, repo)
|
updateReqs, err := b.addUpdate(ctx, batch.Writer, batch.Reader, sha, update, repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -172,7 +174,7 @@ func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha st
|
|||||||
reqs = append(reqs, updateReqs...)
|
reqs = append(reqs, updateReqs...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cancel()
|
batch.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, filename := range changes.RemovedFilenames {
|
for _, filename := range changes.RemovedFilenames {
|
||||||
|
@ -45,7 +45,7 @@ func (p *PullRequest) GetContext() DownloaderContext { return p.Context }
|
|||||||
|
|
||||||
// IsForkPullRequest returns true if the pull request from a forked repository but not the same repository
|
// IsForkPullRequest returns true if the pull request from a forked repository but not the same repository
|
||||||
func (p *PullRequest) IsForkPullRequest() bool {
|
func (p *PullRequest) IsForkPullRequest() bool {
|
||||||
return p.Head.RepoPath() != p.Base.RepoPath()
|
return p.Head.RepoFullName() != p.Base.RepoFullName()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetGitRefName returns pull request relative path to head
|
// GetGitRefName returns pull request relative path to head
|
||||||
@ -62,8 +62,8 @@ type PullRequestBranch struct {
|
|||||||
OwnerName string `yaml:"owner_name"`
|
OwnerName string `yaml:"owner_name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RepoPath returns pull request repo path
|
// RepoFullName returns pull request repo full name
|
||||||
func (p PullRequestBranch) RepoPath() string {
|
func (p PullRequestBranch) RepoFullName() string {
|
||||||
return fmt.Sprintf("%s/%s", p.OwnerName, p.RepoName)
|
return fmt.Sprintf("%s/%s", p.OwnerName, p.RepoName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1274,6 +1274,7 @@ commit_graph.color = Color
|
|||||||
commit.contained_in = This commit is contained in:
|
commit.contained_in = This commit is contained in:
|
||||||
commit.contained_in_default_branch = This commit is part of the default branch
|
commit.contained_in_default_branch = This commit is part of the default branch
|
||||||
commit.load_referencing_branches_and_tags = Load branches and tags referencing this commit
|
commit.load_referencing_branches_and_tags = Load branches and tags referencing this commit
|
||||||
|
commit.load_tags_failed = Load tags failed because of internal error
|
||||||
blame = Blame
|
blame = Blame
|
||||||
download_file = Download file
|
download_file = Download file
|
||||||
normal_view = Normal View
|
normal_view = Normal View
|
||||||
|
@ -628,6 +628,7 @@ org_still_own_repo=Esta organização ainda possui um ou mais repositórios, eli
|
|||||||
org_still_own_packages=Esta organização ainda possui um ou mais pacotes, elimine-os primeiro.
|
org_still_own_packages=Esta organização ainda possui um ou mais pacotes, elimine-os primeiro.
|
||||||
|
|
||||||
target_branch_not_exist=O ramo de destino não existe.
|
target_branch_not_exist=O ramo de destino não existe.
|
||||||
|
target_ref_not_exist=A referência de destino não existe %s
|
||||||
|
|
||||||
admin_cannot_delete_self=Não se pode auto-remover quando tem privilégios de administração. Remova esses privilégios primeiro.
|
admin_cannot_delete_self=Não se pode auto-remover quando tem privilégios de administração. Remova esses privilégios primeiro.
|
||||||
|
|
||||||
@ -1273,6 +1274,7 @@ commit_graph.color=Colorido
|
|||||||
commit.contained_in=Este cometimento está contido em:
|
commit.contained_in=Este cometimento está contido em:
|
||||||
commit.contained_in_default_branch=Este cometimento é parte do ramo principal
|
commit.contained_in_default_branch=Este cometimento é parte do ramo principal
|
||||||
commit.load_referencing_branches_and_tags=Carregar ramos e etiquetas que referenciem este cometimento
|
commit.load_referencing_branches_and_tags=Carregar ramos e etiquetas que referenciem este cometimento
|
||||||
|
commit.load_tags_failed=O carregamento das etiquetas falhou por causa de um erro interno
|
||||||
blame=Responsabilidade
|
blame=Responsabilidade
|
||||||
download_file=Descarregar ficheiro
|
download_file=Descarregar ficheiro
|
||||||
normal_view=Vista normal
|
normal_view=Vista normal
|
||||||
@ -3700,6 +3702,11 @@ workflow.disable_success=A sequência de trabalho '%s' foi desabilitada com suce
|
|||||||
workflow.enable=Habilitar sequência de trabalho
|
workflow.enable=Habilitar sequência de trabalho
|
||||||
workflow.enable_success=A sequência de trabalho '%s' foi habilitada com sucesso.
|
workflow.enable_success=A sequência de trabalho '%s' foi habilitada com sucesso.
|
||||||
workflow.disabled=A sequência de trabalho está desabilitada.
|
workflow.disabled=A sequência de trabalho está desabilitada.
|
||||||
|
workflow.run=Executar sequência de trabalho
|
||||||
|
workflow.not_found=A sequência de trabalho '%s' não foi encontrada.
|
||||||
|
workflow.run_success=A sequência de trabalho '%s' foi executada com sucesso.
|
||||||
|
workflow.from_ref=Usar sequência de trabalho de
|
||||||
|
workflow.has_workflow_dispatch=Esta sequência de trabalho tem um despoletador de eventos workflow_dispatch.
|
||||||
|
|
||||||
need_approval_desc=É necessária aprovação para executar sequências de trabalho para a derivação do pedido de integração.
|
need_approval_desc=É necessária aprovação para executar sequências de trabalho para a derivação do pedido de integração.
|
||||||
|
|
||||||
|
@ -1117,7 +1117,7 @@ projects=Проекты
|
|||||||
packages=Пакеты
|
packages=Пакеты
|
||||||
actions=Действия
|
actions=Действия
|
||||||
labels=Метки
|
labels=Метки
|
||||||
org_labels_desc=Метки уровня организации, которые можно использовать с <strong>всеми репозиториями< / strong> в этой организации
|
org_labels_desc=Метки уровня организации, которые можно использовать с <strong>всеми репозиториями</strong> в этой организации
|
||||||
org_labels_desc_manage=управлять
|
org_labels_desc_manage=управлять
|
||||||
|
|
||||||
milestones=Этапы
|
milestones=Этапы
|
||||||
|
@ -1217,7 +1217,7 @@ clear_ref='Geçerli referansı temizle'
|
|||||||
filter_branch_and_tag=Dal veya biçim imini filtrele
|
filter_branch_and_tag=Dal veya biçim imini filtrele
|
||||||
find_tag=Etiketi bul
|
find_tag=Etiketi bul
|
||||||
branches=Dal
|
branches=Dal
|
||||||
tags=Etiket
|
tags=Etiketler
|
||||||
issues=Konular
|
issues=Konular
|
||||||
pulls=Değişiklik İstekleri
|
pulls=Değişiklik İstekleri
|
||||||
projects=Projeler
|
projects=Projeler
|
||||||
|
@ -40,6 +40,7 @@ func LinkAccount(ctx *context.Context) {
|
|||||||
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
|
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
|
||||||
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
|
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
|
||||||
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
|
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
|
||||||
|
ctx.Data["CfTurnstileSitekey"] = setting.Service.CfTurnstileSitekey
|
||||||
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
|
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
|
||||||
ctx.Data["AllowOnlyInternalRegistration"] = setting.Service.AllowOnlyInternalRegistration
|
ctx.Data["AllowOnlyInternalRegistration"] = setting.Service.AllowOnlyInternalRegistration
|
||||||
ctx.Data["ShowRegistrationButton"] = false
|
ctx.Data["ShowRegistrationButton"] = false
|
||||||
@ -132,6 +133,7 @@ func LinkAccountPostSignIn(ctx *context.Context) {
|
|||||||
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
|
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
|
||||||
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
|
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
|
||||||
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
|
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
|
||||||
|
ctx.Data["CfTurnstileSitekey"] = setting.Service.CfTurnstileSitekey
|
||||||
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
|
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
|
||||||
ctx.Data["ShowRegistrationButton"] = false
|
ctx.Data["ShowRegistrationButton"] = false
|
||||||
|
|
||||||
@ -219,6 +221,7 @@ func LinkAccountPostRegister(ctx *context.Context) {
|
|||||||
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
|
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
|
||||||
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
|
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
|
||||||
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
|
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
|
||||||
|
ctx.Data["CfTurnstileSitekey"] = setting.Service.CfTurnstileSitekey
|
||||||
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
|
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration
|
||||||
ctx.Data["ShowRegistrationButton"] = false
|
ctx.Data["ShowRegistrationButton"] = false
|
||||||
|
|
||||||
|
@ -307,6 +307,7 @@ func RegisterOpenID(ctx *context.Context) {
|
|||||||
ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL
|
ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL
|
||||||
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
|
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
|
||||||
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
|
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
|
||||||
|
ctx.Data["CfTurnstileSitekey"] = setting.Service.CfTurnstileSitekey
|
||||||
ctx.Data["OpenID"] = oid
|
ctx.Data["OpenID"] = oid
|
||||||
userName, _ := ctx.Session.Get("openid_determined_username").(string)
|
userName, _ := ctx.Session.Get("openid_determined_username").(string)
|
||||||
if userName != "" {
|
if userName != "" {
|
||||||
|
@ -83,7 +83,17 @@ func Commits(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["Commits"] = processGitCommits(ctx, commits)
|
ctx.Data["Commits"] = processGitCommits(ctx, commits)
|
||||||
|
commitIDs := make([]string, 0, len(commits))
|
||||||
|
for _, c := range commits {
|
||||||
|
commitIDs = append(commitIDs, c.ID.String())
|
||||||
|
}
|
||||||
|
commitsTagsMap, err := repo_model.FindTagsByCommitIDs(ctx, ctx.Repo.Repository.ID, commitIDs...)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("FindTagsByCommitIDs: %v", err)
|
||||||
|
ctx.Flash.Error(ctx.Tr("repo.commit.load_tags_failed"))
|
||||||
|
} else {
|
||||||
|
ctx.Data["CommitsTagsMap"] = commitsTagsMap
|
||||||
|
}
|
||||||
ctx.Data["Username"] = ctx.Repo.Owner.Name
|
ctx.Data["Username"] = ctx.Repo.Owner.Name
|
||||||
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
|
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
|
||||||
ctx.Data["CommitCount"] = commitsCount
|
ctx.Data["CommitCount"] = commitsCount
|
||||||
|
@ -240,7 +240,8 @@ func SettingsPost(ctx *context.Context) {
|
|||||||
|
|
||||||
remoteAddress, err := util.SanitizeURL(form.MirrorAddress)
|
remoteAddress, err := util.SanitizeURL(form.MirrorAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("SanitizeURL", err)
|
ctx.Data["Err_MirrorAddress"] = true
|
||||||
|
handleSettingRemoteAddrError(ctx, err, form)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pullMirror.RemoteAddress = remoteAddress
|
pullMirror.RemoteAddress = remoteAddress
|
||||||
@ -401,7 +402,8 @@ func SettingsPost(ctx *context.Context) {
|
|||||||
|
|
||||||
remoteAddress, err := util.SanitizeURL(form.PushMirrorAddress)
|
remoteAddress, err := util.SanitizeURL(form.PushMirrorAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("SanitizeURL", err)
|
ctx.Data["Err_PushMirrorAddress"] = true
|
||||||
|
handleSettingRemoteAddrError(ctx, err, form)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +386,7 @@ func (n *actionsNotifier) ForkRepository(ctx context.Context, doer *user_model.U
|
|||||||
// Add to hook queue for created repo after session commit.
|
// Add to hook queue for created repo after session commit.
|
||||||
if u.IsOrganization() {
|
if u.IsOrganization() {
|
||||||
newNotifyInput(repo, doer, webhook_module.HookEventRepository).
|
newNotifyInput(repo, doer, webhook_module.HookEventRepository).
|
||||||
WithRef(oldRepo.DefaultBranch).
|
WithRef(git.RefNameFromBranch(oldRepo.DefaultBranch).String()).
|
||||||
WithPayload(&api.RepositoryPayload{
|
WithPayload(&api.RepositoryPayload{
|
||||||
Action: api.HookRepoCreated,
|
Action: api.HookRepoCreated,
|
||||||
Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}),
|
Repository: convert.ToRepo(ctx, repo, access_model.Permission{AccessMode: perm_model.AccessModeOwner}),
|
||||||
|
@ -65,7 +65,7 @@ type notifyInput struct {
|
|||||||
Event webhook_module.HookEventType
|
Event webhook_module.HookEventType
|
||||||
|
|
||||||
// optional
|
// optional
|
||||||
Ref string
|
Ref git.RefName
|
||||||
Payload api.Payloader
|
Payload api.Payloader
|
||||||
PullRequest *issues_model.PullRequest
|
PullRequest *issues_model.PullRequest
|
||||||
}
|
}
|
||||||
@ -89,7 +89,7 @@ func (input *notifyInput) WithDoer(doer *user_model.User) *notifyInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (input *notifyInput) WithRef(ref string) *notifyInput {
|
func (input *notifyInput) WithRef(ref string) *notifyInput {
|
||||||
input.Ref = ref
|
input.Ref = git.RefName(ref)
|
||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ func (input *notifyInput) WithPayload(payload api.Payloader) *notifyInput {
|
|||||||
func (input *notifyInput) WithPullRequest(pr *issues_model.PullRequest) *notifyInput {
|
func (input *notifyInput) WithPullRequest(pr *issues_model.PullRequest) *notifyInput {
|
||||||
input.PullRequest = pr
|
input.PullRequest = pr
|
||||||
if input.Ref == "" {
|
if input.Ref == "" {
|
||||||
input.Ref = pr.GetGitRefName()
|
input.Ref = git.RefName(pr.GetGitRefName())
|
||||||
}
|
}
|
||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
@ -144,20 +144,25 @@ func notify(ctx context.Context, input *notifyInput) error {
|
|||||||
defer gitRepo.Close()
|
defer gitRepo.Close()
|
||||||
|
|
||||||
ref := input.Ref
|
ref := input.Ref
|
||||||
if ref != input.Repo.DefaultBranch && actions_module.IsDefaultBranchWorkflow(input.Event) {
|
if ref.BranchName() != input.Repo.DefaultBranch && actions_module.IsDefaultBranchWorkflow(input.Event) {
|
||||||
if ref != "" {
|
if ref != "" {
|
||||||
log.Warn("Event %q should only trigger workflows on the default branch, but its ref is %q. Will fall back to the default branch",
|
log.Warn("Event %q should only trigger workflows on the default branch, but its ref is %q. Will fall back to the default branch",
|
||||||
input.Event, ref)
|
input.Event, ref)
|
||||||
}
|
}
|
||||||
ref = input.Repo.DefaultBranch
|
ref = git.RefNameFromBranch(input.Repo.DefaultBranch)
|
||||||
}
|
}
|
||||||
if ref == "" {
|
if ref == "" {
|
||||||
log.Warn("Ref of event %q is empty, will fall back to the default branch", input.Event)
|
log.Warn("Ref of event %q is empty, will fall back to the default branch", input.Event)
|
||||||
ref = input.Repo.DefaultBranch
|
ref = git.RefNameFromBranch(input.Repo.DefaultBranch)
|
||||||
|
}
|
||||||
|
|
||||||
|
commitID, err := gitRepo.GetRefCommitID(ref.String())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("gitRepo.GetRefCommitID: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the commit object for the ref
|
// Get the commit object for the ref
|
||||||
commit, err := gitRepo.GetCommit(ref)
|
commit, err := gitRepo.GetCommit(commitID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("gitRepo.GetCommit: %w", err)
|
return fmt.Errorf("gitRepo.GetCommit: %w", err)
|
||||||
}
|
}
|
||||||
@ -168,7 +173,7 @@ func notify(ctx context.Context, input *notifyInput) error {
|
|||||||
|
|
||||||
var detectedWorkflows []*actions_module.DetectedWorkflow
|
var detectedWorkflows []*actions_module.DetectedWorkflow
|
||||||
actionsConfig := input.Repo.MustGetUnit(ctx, unit_model.TypeActions).ActionsConfig()
|
actionsConfig := input.Repo.MustGetUnit(ctx, unit_model.TypeActions).ActionsConfig()
|
||||||
shouldDetectSchedules := input.Event == webhook_module.HookEventPush && git.RefName(input.Ref).BranchName() == input.Repo.DefaultBranch
|
shouldDetectSchedules := input.Event == webhook_module.HookEventPush && input.Ref.BranchName() == input.Repo.DefaultBranch
|
||||||
workflows, schedules, err := actions_module.DetectWorkflows(gitRepo, commit,
|
workflows, schedules, err := actions_module.DetectWorkflows(gitRepo, commit,
|
||||||
input.Event,
|
input.Event,
|
||||||
input.Payload,
|
input.Payload,
|
||||||
@ -220,12 +225,12 @@ func notify(ctx context.Context, input *notifyInput) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if shouldDetectSchedules {
|
if shouldDetectSchedules {
|
||||||
if err := handleSchedules(ctx, schedules, commit, input, ref); err != nil {
|
if err := handleSchedules(ctx, schedules, commit, input, ref.String()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return handleWorkflows(ctx, detectedWorkflows, commit, input, ref)
|
return handleWorkflows(ctx, detectedWorkflows, commit, input, ref.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func skipWorkflows(input *notifyInput, commit *git.Commit) bool {
|
func skipWorkflows(input *notifyInput, commit *git.Commit) bool {
|
||||||
|
@ -245,9 +245,21 @@ func handlePullRequestAutoMerge(pullID int64, sha string) {
|
|||||||
defer headGitRepo.Close()
|
defer headGitRepo.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
headBranchExist := headGitRepo.IsBranchExist(pr.HeadBranch)
|
switch pr.Flow {
|
||||||
if pr.HeadRepo == nil || !headBranchExist {
|
case issues_model.PullRequestFlowGithub:
|
||||||
log.Warn("Head branch of auto merge %-v does not exist [HeadRepoID: %d, Branch: %s]", pr, pr.HeadRepoID, pr.HeadBranch)
|
headBranchExist := headGitRepo.IsBranchExist(pr.HeadBranch)
|
||||||
|
if pr.HeadRepo == nil || !headBranchExist {
|
||||||
|
log.Warn("Head branch of auto merge %-v does not exist [HeadRepoID: %d, Branch: %s]", pr, pr.HeadRepoID, pr.HeadBranch)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case issues_model.PullRequestFlowAGit:
|
||||||
|
headBranchExist := git.IsReferenceExist(ctx, baseGitRepo.Path, pr.GetGitRefName())
|
||||||
|
if !headBranchExist {
|
||||||
|
log.Warn("Head branch of auto merge %-v does not exist [HeadRepoID: %d, Branch(Agit): %s]", pr, pr.HeadRepoID, pr.HeadBranch)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Error("wrong flow type %d", pr.Flow)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,9 +20,11 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<div class="flex-text-block">
|
<div class="flex-text-block">
|
||||||
{{if .DefaultBranchBranch.IsProtected}}{{svg "octicon-shield-lock"}}{{end}}
|
|
||||||
<a class="gt-ellipsis" href="{{.RepoLink}}/src/branch/{{PathEscapeSegments .DefaultBranchBranch.DBBranch.Name}}">{{.DefaultBranchBranch.DBBranch.Name}}</a>
|
<a class="gt-ellipsis" href="{{.RepoLink}}/src/branch/{{PathEscapeSegments .DefaultBranchBranch.DBBranch.Name}}">{{.DefaultBranchBranch.DBBranch.Name}}</a>
|
||||||
<button class="btn interact-fg tw-px-1" data-clipboard-text="{{.DefaultBranchBranch.DBBranch.Name}}">{{svg "octicon-copy" 14}}</button>
|
{{if .DefaultBranchBranch.IsProtected}}
|
||||||
|
<span data-tooltip-content="{{ctx.Locale.Tr "repo.settings.protected_branch"}}">{{svg "octicon-shield-lock"}}</span>
|
||||||
|
{{end}}
|
||||||
|
<button class="btn interact-fg tw-px-1" data-clipboard-text="{{.DefaultBranchBranch.DBBranch.Name}}" data-tooltip-content="{{ctx.Locale.Tr "copy_branch"}}">{{svg "octicon-copy" 14}}</button>
|
||||||
{{template "repo/commit_statuses" dict "Status" (index $.CommitStatus .DefaultBranchBranch.DBBranch.CommitID) "Statuses" (index $.CommitStatuses .DefaultBranchBranch.DBBranch.CommitID)}}
|
{{template "repo/commit_statuses" dict "Status" (index $.CommitStatus .DefaultBranchBranch.DBBranch.CommitID) "Statuses" (index $.CommitStatuses .DefaultBranchBranch.DBBranch.CommitID)}}
|
||||||
</div>
|
</div>
|
||||||
<p class="info tw-flex tw-items-center tw-my-1">{{svg "octicon-git-commit" 16 "tw-mr-1"}}<a href="{{.RepoLink}}/commit/{{PathEscape .DefaultBranchBranch.DBBranch.CommitID}}">{{ShortSha .DefaultBranchBranch.DBBranch.CommitID}}</a> · <span class="commit-message">{{RenderCommitMessage $.Context .DefaultBranchBranch.DBBranch.CommitMessage (.Repository.ComposeMetas ctx)}}</span> · {{ctx.Locale.Tr "org.repo_updated"}} {{TimeSince .DefaultBranchBranch.DBBranch.CommitTime.AsTime ctx.Locale}}{{if .DefaultBranchBranch.DBBranch.Pusher}} {{template "shared/user/avatarlink" dict "user" .DefaultBranchBranch.DBBranch.Pusher}}{{template "shared/user/namelink" .DefaultBranchBranch.DBBranch.Pusher}}{{end}}</p>
|
<p class="info tw-flex tw-items-center tw-my-1">{{svg "octicon-git-commit" 16 "tw-mr-1"}}<a href="{{.RepoLink}}/commit/{{PathEscape .DefaultBranchBranch.DBBranch.CommitID}}">{{ShortSha .DefaultBranchBranch.DBBranch.CommitID}}</a> · <span class="commit-message">{{RenderCommitMessage $.Context .DefaultBranchBranch.DBBranch.CommitMessage (.Repository.ComposeMetas ctx)}}</span> · {{ctx.Locale.Tr "org.repo_updated"}} {{TimeSince .DefaultBranchBranch.DBBranch.CommitTime.AsTime ctx.Locale}}{{if .DefaultBranchBranch.DBBranch.Pusher}} {{template "shared/user/avatarlink" dict "user" .DefaultBranchBranch.DBBranch.Pusher}}{{template "shared/user/namelink" .DefaultBranchBranch.DBBranch.Pusher}}{{end}}</p>
|
||||||
@ -39,7 +41,7 @@
|
|||||||
</button>
|
</button>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .EnableFeed}}
|
{{if .EnableFeed}}
|
||||||
<a role="button" class="btn interact-bg tw-p-2" href="{{$.FeedURL}}/rss/branch/{{PathEscapeSegments .DefaultBranchBranch.DBBranch.Name}}">{{svg "octicon-rss"}}</a>
|
<a role="button" class="btn interact-bg tw-p-2" href="{{$.FeedURL}}/rss/branch/{{PathEscapeSegments .DefaultBranchBranch.DBBranch.Name}}" data-tooltip-content="{{ctx.Locale.Tr "rss_feed"}}">{{svg "octicon-rss"}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if not $.DisableDownloadSourceArchives}}
|
{{if not $.DisableDownloadSourceArchives}}
|
||||||
<div class="ui dropdown btn interact-bg tw-p-2" data-tooltip-content="{{ctx.Locale.Tr "repo.branch.download" ($.DefaultBranchBranch.DBBranch.Name)}}">
|
<div class="ui dropdown btn interact-bg tw-p-2" data-tooltip-content="{{ctx.Locale.Tr "repo.branch.download" ($.DefaultBranchBranch.DBBranch.Name)}}">
|
||||||
@ -88,14 +90,16 @@
|
|||||||
{{if .DBBranch.IsDeleted}}
|
{{if .DBBranch.IsDeleted}}
|
||||||
<div class="flex-text-block">
|
<div class="flex-text-block">
|
||||||
<span class="gt-ellipsis">{{.DBBranch.Name}}</span>
|
<span class="gt-ellipsis">{{.DBBranch.Name}}</span>
|
||||||
<button class="btn interact-fg tw-px-1" data-clipboard-text="{{.DBBranch.Name}}">{{svg "octicon-copy" 14}}</button>
|
<button class="btn interact-fg tw-px-1" data-clipboard-text="{{.DBBranch.Name}}" data-tooltip-content="{{ctx.Locale.Tr "copy_branch"}}">{{svg "octicon-copy" 14}}</button>
|
||||||
</div>
|
</div>
|
||||||
<p class="info">{{ctx.Locale.Tr "repo.branch.deleted_by" .DBBranch.DeletedBy.Name}} {{TimeSinceUnix .DBBranch.DeletedUnix ctx.Locale}}</p>
|
<p class="info">{{ctx.Locale.Tr "repo.branch.deleted_by" .DBBranch.DeletedBy.Name}} {{TimeSinceUnix .DBBranch.DeletedUnix ctx.Locale}}</p>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="flex-text-block">
|
<div class="flex-text-block">
|
||||||
{{if .IsProtected}}{{svg "octicon-shield-lock"}}{{end}}
|
|
||||||
<a class="gt-ellipsis" href="{{$.RepoLink}}/src/branch/{{PathEscapeSegments .DBBranch.Name}}">{{.DBBranch.Name}}</a>
|
<a class="gt-ellipsis" href="{{$.RepoLink}}/src/branch/{{PathEscapeSegments .DBBranch.Name}}">{{.DBBranch.Name}}</a>
|
||||||
<button class="btn interact-fg tw-px-1" data-clipboard-text="{{.DBBranch.Name}}">{{svg "octicon-copy" 14}}</button>
|
{{if .IsProtected}}
|
||||||
|
<span data-tooltip-content="{{ctx.Locale.Tr "repo.settings.protected_branch"}}">{{svg "octicon-shield-lock"}}</span>
|
||||||
|
{{end}}
|
||||||
|
<button class="btn interact-fg tw-px-1" data-clipboard-text="{{.DBBranch.Name}}" data-tooltip-content="{{ctx.Locale.Tr "copy_branch"}}">{{svg "octicon-copy" 14}}</button>
|
||||||
{{template "repo/commit_statuses" dict "Status" (index $.CommitStatus .DBBranch.CommitID) "Statuses" (index $.CommitStatuses .DBBranch.CommitID)}}
|
{{template "repo/commit_statuses" dict "Status" (index $.CommitStatus .DBBranch.CommitID) "Statuses" (index $.CommitStatuses .DBBranch.CommitID)}}
|
||||||
</div>
|
</div>
|
||||||
<p class="info tw-flex tw-items-center tw-my-1">{{svg "octicon-git-commit" 16 "tw-mr-1"}}<a href="{{$.RepoLink}}/commit/{{PathEscape .DBBranch.CommitID}}">{{ShortSha .DBBranch.CommitID}}</a> · <span class="commit-message">{{RenderCommitMessage $.Context .DBBranch.CommitMessage ($.Repository.ComposeMetas ctx)}}</span> · {{ctx.Locale.Tr "org.repo_updated"}} {{TimeSince .DBBranch.CommitTime.AsTime ctx.Locale}}{{if .DBBranch.Pusher}} {{template "shared/user/avatarlink" dict "user" .DBBranch.Pusher}} {{template "shared/user/namelink" .DBBranch.Pusher}}{{end}}</p>
|
<p class="info tw-flex tw-items-center tw-my-1">{{svg "octicon-git-commit" 16 "tw-mr-1"}}<a href="{{$.RepoLink}}/commit/{{PathEscape .DBBranch.CommitID}}">{{ShortSha .DBBranch.CommitID}}</a> · <span class="commit-message">{{RenderCommitMessage $.Context .DBBranch.CommitMessage ($.Repository.ComposeMetas ctx)}}</span> · {{ctx.Locale.Tr "org.repo_updated"}} {{TimeSince .DBBranch.CommitTime.AsTime ctx.Locale}}{{if .DBBranch.Pusher}} {{template "shared/user/avatarlink" dict "user" .DBBranch.Pusher}} {{template "shared/user/namelink" .DBBranch.Pusher}}{{end}}</p>
|
||||||
@ -156,7 +160,7 @@
|
|||||||
</button>
|
</button>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if $.EnableFeed}}
|
{{if $.EnableFeed}}
|
||||||
<a role="button" class="btn interact-bg tw-p-2" href="{{$.FeedURL}}/rss/branch/{{PathEscapeSegments .DBBranch.Name}}">{{svg "octicon-rss"}}</a>
|
<a role="button" class="btn interact-bg tw-p-2" href="{{$.FeedURL}}/rss/branch/{{PathEscapeSegments .DBBranch.Name}}" data-tooltip-content="{{ctx.Locale.Tr "rss_feed"}}">{{svg "octicon-rss"}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if and (not .DBBranch.IsDeleted) (not $.DisableDownloadSourceArchives)}}
|
{{if and (not .DBBranch.IsDeleted) (not $.DisableDownloadSourceArchives)}}
|
||||||
<div class="ui dropdown btn interact-bg tw-p-2" data-tooltip-content="{{ctx.Locale.Tr "repo.branch.download" (.DBBranch.Name)}}">
|
<div class="ui dropdown btn interact-bg tw-p-2" data-tooltip-content="{{ctx.Locale.Tr "repo.branch.download" (.DBBranch.Name)}}">
|
||||||
|
@ -72,6 +72,11 @@
|
|||||||
{{if IsMultilineCommitMessage .Message}}
|
{{if IsMultilineCommitMessage .Message}}
|
||||||
<pre class="commit-body tw-hidden">{{RenderCommitBody $.Context .Message ($.Repository.ComposeMetas ctx)}}</pre>
|
<pre class="commit-body tw-hidden">{{RenderCommitBody $.Context .Message ($.Repository.ComposeMetas ctx)}}</pre>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{if $.CommitsTagsMap}}
|
||||||
|
{{range (index $.CommitsTagsMap .ID.String)}}
|
||||||
|
{{- template "repo/tag/name" dict "RepoLink" $.Repository.Link "TagName" .TagName "IsRelease" (not .IsTag) -}}
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
</td>
|
</td>
|
||||||
{{if .Committer}}
|
{{if .Committer}}
|
||||||
<td class="text right aligned">{{TimeSince .Committer.When ctx.Locale}}</td>
|
<td class="text right aligned">{{TimeSince .Committer.When ctx.Locale}}</td>
|
||||||
|
@ -42,9 +42,7 @@
|
|||||||
</a>
|
</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else if eq $refGroup "tags"}}
|
{{else if eq $refGroup "tags"}}
|
||||||
<a class="ui labelled basic tiny button" href="{{$.RepoLink}}/src/tag/{{.ShortName|PathEscape}}">
|
{{- template "repo/tag/name" dict "RepoLink" $.Repository.Link "TagName" .ShortName -}}
|
||||||
{{svg "octicon-tag"}} {{.ShortName}}
|
|
||||||
</a>
|
|
||||||
{{else if eq $refGroup "remotes"}}
|
{{else if eq $refGroup "remotes"}}
|
||||||
<a class="ui labelled basic tiny button" href="{{$.RepoLink}}/src/commit/{{$commit.Rev|PathEscape}}">
|
<a class="ui labelled basic tiny button" href="{{$.RepoLink}}/src/commit/{{$commit.Rev|PathEscape}}">
|
||||||
{{svg "octicon-cross-reference"}} {{.ShortName}}
|
{{svg "octicon-cross-reference"}} {{.ShortName}}
|
||||||
|
3
templates/repo/tag/name.tmpl
Normal file
3
templates/repo/tag/name.tmpl
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<a class="ui label basic tiny button{{if .IsRelease}} primary{{end}}" href="{{.RepoLink}}/src/tag/{{.TagName|PathEscape}}">
|
||||||
|
{{svg "octicon-tag"}} {{.TagName}}
|
||||||
|
</a>
|
7
tests/gitea-repositories-meta/user2/repo1.git/hooks/proc-receive
Executable file
7
tests/gitea-repositories-meta/user2/repo1.git/hooks/proc-receive
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
ORI_DIR=`pwd`
|
||||||
|
SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
|
||||||
|
cd "$ORI_DIR"
|
||||||
|
for i in `ls "$SHELL_FOLDER/proc-receive.d"`; do
|
||||||
|
sh "$SHELL_FOLDER/proc-receive.d/$i"
|
||||||
|
done
|
2
tests/gitea-repositories-meta/user2/repo1.git/hooks/proc-receive.d/gitea
Executable file
2
tests/gitea-repositories-meta/user2/repo1.git/hooks/proc-receive.d/gitea
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" proc-receive
|
@ -427,7 +427,7 @@ func TestCreateDeleteRefEvent(t *testing.T) {
|
|||||||
Title: "add workflow",
|
Title: "add workflow",
|
||||||
RepoID: repo.ID,
|
RepoID: repo.ID,
|
||||||
Event: "delete",
|
Event: "delete",
|
||||||
Ref: "main",
|
Ref: "refs/heads/main",
|
||||||
WorkflowID: "createdelete.yml",
|
WorkflowID: "createdelete.yml",
|
||||||
CommitSHA: branch.CommitID,
|
CommitSHA: branch.CommitID,
|
||||||
})
|
})
|
||||||
@ -442,7 +442,7 @@ func TestCreateDeleteRefEvent(t *testing.T) {
|
|||||||
Title: "add workflow",
|
Title: "add workflow",
|
||||||
RepoID: repo.ID,
|
RepoID: repo.ID,
|
||||||
Event: "delete",
|
Event: "delete",
|
||||||
Ref: "main",
|
Ref: "refs/heads/main",
|
||||||
WorkflowID: "createdelete.yml",
|
WorkflowID: "createdelete.yml",
|
||||||
CommitSHA: branch.CommitID,
|
CommitSHA: branch.CommitID,
|
||||||
})
|
})
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/gitrepo"
|
"code.gitea.io/gitea/modules/gitrepo"
|
||||||
"code.gitea.io/gitea/modules/queue"
|
"code.gitea.io/gitea/modules/queue"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/test"
|
"code.gitea.io/gitea/modules/test"
|
||||||
"code.gitea.io/gitea/modules/translation"
|
"code.gitea.io/gitea/modules/translation"
|
||||||
@ -846,3 +847,132 @@ func TestPullAutoMergeAfterCommitStatusSucceedAndApproval(t *testing.T) {
|
|||||||
unittest.AssertNotExistsBean(t, &pull_model.AutoMerge{PullID: pr.ID})
|
unittest.AssertNotExistsBean(t, &pull_model.AutoMerge{PullID: pr.ID})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPullAutoMergeAfterCommitStatusSucceedAndApprovalForAgitFlow(t *testing.T) {
|
||||||
|
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||||
|
// create a pull request
|
||||||
|
baseAPITestContext := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||||
|
|
||||||
|
dstPath := t.TempDir()
|
||||||
|
|
||||||
|
u.Path = baseAPITestContext.GitPath()
|
||||||
|
u.User = url.UserPassword("user2", userPassword)
|
||||||
|
|
||||||
|
t.Run("Clone", doGitClone(dstPath, u))
|
||||||
|
|
||||||
|
err := os.WriteFile(path.Join(dstPath, "test_file"), []byte("## test content"), 0o666)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = git.AddChanges(dstPath, true)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = git.CommitChanges(dstPath, git.CommitChangesOptions{
|
||||||
|
Committer: &git.Signature{
|
||||||
|
Email: "user2@example.com",
|
||||||
|
Name: "user2",
|
||||||
|
When: time.Now(),
|
||||||
|
},
|
||||||
|
Author: &git.Signature{
|
||||||
|
Email: "user2@example.com",
|
||||||
|
Name: "user2",
|
||||||
|
When: time.Now(),
|
||||||
|
},
|
||||||
|
Message: "Testing commit 1",
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
stderrBuf := &bytes.Buffer{}
|
||||||
|
|
||||||
|
err = git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master", "-o").
|
||||||
|
AddDynamicArguments(`topic=test/head2`).
|
||||||
|
AddArguments("-o").
|
||||||
|
AddDynamicArguments(`title="create a test pull request with agit"`).
|
||||||
|
AddArguments("-o").
|
||||||
|
AddDynamicArguments(`description="This PR is a test pull request which created with agit"`).
|
||||||
|
Run(&git.RunOpts{Dir: dstPath, Stderr: stderrBuf})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Contains(t, stderrBuf.String(), setting.AppURL+"user2/repo1/pulls/6")
|
||||||
|
|
||||||
|
baseRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user2", Name: "repo1"})
|
||||||
|
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{
|
||||||
|
Flow: issues_model.PullRequestFlowAGit,
|
||||||
|
BaseRepoID: baseRepo.ID,
|
||||||
|
BaseBranch: "master",
|
||||||
|
HeadRepoID: baseRepo.ID,
|
||||||
|
HeadBranch: "user2/test/head2",
|
||||||
|
})
|
||||||
|
|
||||||
|
session := loginUser(t, "user1")
|
||||||
|
// add protected branch for commit status
|
||||||
|
csrf := GetCSRF(t, session, "/user2/repo1/settings/branches")
|
||||||
|
// Change master branch to protected
|
||||||
|
req := NewRequestWithValues(t, "POST", "/user2/repo1/settings/branches/edit", map[string]string{
|
||||||
|
"_csrf": csrf,
|
||||||
|
"rule_name": "master",
|
||||||
|
"enable_push": "true",
|
||||||
|
"enable_status_check": "true",
|
||||||
|
"status_check_contexts": "gitea/actions",
|
||||||
|
"required_approvals": "1",
|
||||||
|
})
|
||||||
|
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||||
|
|
||||||
|
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
|
// first time insert automerge record, return true
|
||||||
|
scheduled, err := automerge.ScheduleAutoMerge(db.DefaultContext, user1, pr, repo_model.MergeStyleMerge, "auto merge test")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, scheduled)
|
||||||
|
|
||||||
|
// second time insert automerge record, return false because it does exist
|
||||||
|
scheduled, err = automerge.ScheduleAutoMerge(db.DefaultContext, user1, pr, repo_model.MergeStyleMerge, "auto merge test")
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.False(t, scheduled)
|
||||||
|
|
||||||
|
// reload pr again
|
||||||
|
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
|
||||||
|
assert.False(t, pr.HasMerged)
|
||||||
|
assert.Empty(t, pr.MergedCommitID)
|
||||||
|
|
||||||
|
// update commit status to success, then it should be merged automatically
|
||||||
|
baseGitRepo, err := gitrepo.OpenRepository(db.DefaultContext, baseRepo)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
sha, err := baseGitRepo.GetRefCommitID(pr.GetGitRefName())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
masterCommitID, err := baseGitRepo.GetBranchCommitID("master")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
baseGitRepo.Close()
|
||||||
|
defer func() {
|
||||||
|
testResetRepo(t, baseRepo.RepoPath(), "master", masterCommitID)
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = commitstatus_service.CreateCommitStatus(db.DefaultContext, baseRepo, user1, sha, &git_model.CommitStatus{
|
||||||
|
State: api.CommitStatusSuccess,
|
||||||
|
TargetURL: "https://gitea.com",
|
||||||
|
Context: "gitea/actions",
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
|
// reload pr again
|
||||||
|
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
|
||||||
|
assert.False(t, pr.HasMerged)
|
||||||
|
assert.Empty(t, pr.MergedCommitID)
|
||||||
|
|
||||||
|
// approve the PR from non-author
|
||||||
|
approveSession := loginUser(t, "user1")
|
||||||
|
req = NewRequest(t, "GET", fmt.Sprintf("/user2/repo1/pulls/%d", pr.Index))
|
||||||
|
resp := approveSession.MakeRequest(t, req, http.StatusOK)
|
||||||
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
|
testSubmitReview(t, approveSession, htmlDoc.GetCSRF(), "user2", "repo1", strconv.Itoa(int(pr.Index)), sha, "approve", http.StatusOK)
|
||||||
|
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
|
// realod pr again
|
||||||
|
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
|
||||||
|
assert.True(t, pr.HasMerged)
|
||||||
|
assert.NotEmpty(t, pr.MergedCommitID)
|
||||||
|
|
||||||
|
unittest.AssertNotExistsBean(t, &pull_model.AutoMerge{PullID: pr.ID})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user