* Added MirrorInterval to the API * Remove MirrorInterval from CreateRepository * Removed Duplicate UpdateMirror Function * Updated Error Logging * Update Log Message for is not Mirror Co-authored-by: 6543 <6543@obermui.de> * Delete Debug Statement that snuck in Co-authored-by: zeripath <art27@cantab.net> * Add Check for If Interval is too small * Output to API Call * Add Error Object when time is Less than Min Interval * Frequency Error Message Co-authored-by: zeripath <art27@cantab.net> * Allow Zero Mirror Interval Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>tags/v1.15.0-dev
@@ -979,6 +979,7 @@ type CreateRepoOptions struct { | |||||
AutoInit bool | AutoInit bool | ||||
Status RepositoryStatus | Status RepositoryStatus | ||||
TrustModel TrustModelType | TrustModel TrustModelType | ||||
MirrorInterval string | |||||
} | } | ||||
// GetRepoInitFile returns repository init files | // GetRepoInitFile returns repository init files | ||||
@@ -68,16 +68,17 @@ type MigrateRepoForm struct { | |||||
// required: true | // required: true | ||||
UID int64 `json:"uid" binding:"Required"` | UID int64 `json:"uid" binding:"Required"` | ||||
// required: true | // required: true | ||||
RepoName string `json:"repo_name" binding:"Required;AlphaDashDot;MaxSize(100)"` | |||||
Mirror bool `json:"mirror"` | |||||
Private bool `json:"private"` | |||||
Description string `json:"description" binding:"MaxSize(255)"` | |||||
Wiki bool `json:"wiki"` | |||||
Milestones bool `json:"milestones"` | |||||
Labels bool `json:"labels"` | |||||
Issues bool `json:"issues"` | |||||
PullRequests bool `json:"pull_requests"` | |||||
Releases bool `json:"releases"` | |||||
RepoName string `json:"repo_name" binding:"Required;AlphaDashDot;MaxSize(100)"` | |||||
Mirror bool `json:"mirror"` | |||||
Private bool `json:"private"` | |||||
Description string `json:"description" binding:"MaxSize(255)"` | |||||
Wiki bool `json:"wiki"` | |||||
Milestones bool `json:"milestones"` | |||||
Labels bool `json:"labels"` | |||||
Issues bool `json:"issues"` | |||||
PullRequests bool `json:"pull_requests"` | |||||
Releases bool `json:"releases"` | |||||
MirrorInterval string `json:"mirror_interval"` | |||||
} | } | ||||
// Validate validates the fields | // Validate validates the fields | ||||
@@ -91,6 +91,13 @@ func innerToRepo(repo *models.Repository, mode models.AccessMode, isParent bool) | |||||
numReleases, _ := models.GetReleaseCountByRepoID(repo.ID, models.FindReleasesOptions{IncludeDrafts: false, IncludeTags: true}) | numReleases, _ := models.GetReleaseCountByRepoID(repo.ID, models.FindReleasesOptions{IncludeDrafts: false, IncludeTags: true}) | ||||
mirrorInterval := "" | |||||
if repo.IsMirror { | |||||
if err := repo.GetMirror(); err == nil { | |||||
mirrorInterval = repo.Mirror.Interval.String() | |||||
} | |||||
} | |||||
return &api.Repository{ | return &api.Repository{ | ||||
ID: repo.ID, | ID: repo.ID, | ||||
Owner: ToUser(repo.Owner, mode != models.AccessModeNone, mode >= models.AccessModeAdmin), | Owner: ToUser(repo.Owner, mode != models.AccessModeNone, mode >= models.AccessModeAdmin), | ||||
@@ -134,5 +141,6 @@ func innerToRepo(repo *models.Repository, mode models.AccessMode, isParent bool) | |||||
AllowSquash: allowSquash, | AllowSquash: allowSquash, | ||||
AvatarURL: repo.AvatarLink(), | AvatarURL: repo.AvatarLink(), | ||||
Internal: !repo.IsPrivate && repo.Owner.Visibility == api.VisibleTypePrivate, | Internal: !repo.IsPrivate && repo.Owner.Visibility == api.VisibleTypePrivate, | ||||
MirrorInterval: mirrorInterval, | |||||
} | } | ||||
} | } |
@@ -33,4 +33,5 @@ type MigrateOptions struct { | |||||
PullRequests bool | PullRequests bool | ||||
ReleaseAssets bool | ReleaseAssets bool | ||||
MigrateToRepoID int64 | MigrateToRepoID int64 | ||||
MirrorInterval string `json:"mirror_interval"` | |||||
} | } |
@@ -142,6 +142,7 @@ func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.Migrate | |||||
Private: repo.IsPrivate, | Private: repo.IsPrivate, | ||||
Wiki: opts.Wiki, | Wiki: opts.Wiki, | ||||
Releases: opts.Releases, // if didn't get releases, then sync them from tags | Releases: opts.Releases, // if didn't get releases, then sync them from tags | ||||
MirrorInterval: opts.MirrorInterval, | |||||
}) | }) | ||||
g.repo = r | g.repo = r | ||||
@@ -127,12 +127,33 @@ func MigrateRepositoryGitData(ctx context.Context, u *models.User, repo *models. | |||||
} | } | ||||
if opts.Mirror { | if opts.Mirror { | ||||
if err = models.InsertMirror(&models.Mirror{ | |||||
mirrorModel := models.Mirror{ | |||||
RepoID: repo.ID, | RepoID: repo.ID, | ||||
Interval: setting.Mirror.DefaultInterval, | Interval: setting.Mirror.DefaultInterval, | ||||
EnablePrune: true, | EnablePrune: true, | ||||
NextUpdateUnix: timeutil.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval), | NextUpdateUnix: timeutil.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval), | ||||
}); err != nil { | |||||
} | |||||
if opts.MirrorInterval != "" { | |||||
parsedInterval, err := time.ParseDuration(opts.MirrorInterval) | |||||
if err != nil { | |||||
log.Error("Failed to set Interval: %v", err) | |||||
return repo, err | |||||
} | |||||
if parsedInterval == 0 { | |||||
mirrorModel.Interval = 0 | |||||
mirrorModel.NextUpdateUnix = 0 | |||||
} else if parsedInterval < setting.Mirror.MinInterval { | |||||
err := fmt.Errorf("Interval %s is set below Minimum Interval of %s", parsedInterval, setting.Mirror.MinInterval) | |||||
log.Error("Interval: %s is too frequent", opts.MirrorInterval) | |||||
return repo, err | |||||
} else { | |||||
mirrorModel.Interval = parsedInterval | |||||
mirrorModel.NextUpdateUnix = timeutil.TimeStampNow().AddDuration(parsedInterval) | |||||
} | |||||
} | |||||
if err = models.InsertMirror(&mirrorModel); err != nil { | |||||
return repo, fmt.Errorf("InsertOne: %v", err) | return repo, fmt.Errorf("InsertOne: %v", err) | ||||
} | } | ||||
@@ -91,6 +91,7 @@ type Repository struct { | |||||
AllowSquash bool `json:"allow_squash_merge"` | AllowSquash bool `json:"allow_squash_merge"` | ||||
AvatarURL string `json:"avatar_url"` | AvatarURL string `json:"avatar_url"` | ||||
Internal bool `json:"internal"` | Internal bool `json:"internal"` | ||||
MirrorInterval string `json:"mirror_interval"` | |||||
} | } | ||||
// CreateRepoOption options when creating repository | // CreateRepoOption options when creating repository | ||||
@@ -168,6 +169,8 @@ type EditRepoOption struct { | |||||
AllowSquash *bool `json:"allow_squash_merge,omitempty"` | AllowSquash *bool `json:"allow_squash_merge,omitempty"` | ||||
// set to `true` to archive this repository. | // set to `true` to archive this repository. | ||||
Archived *bool `json:"archived,omitempty"` | Archived *bool `json:"archived,omitempty"` | ||||
// set to a string like `8h30m0s` to set the mirror interval time | |||||
MirrorInterval *string `json:"mirror_interval,omitempty"` | |||||
} | } | ||||
// CreateBranchRepoOption options when creating a branch in a repository | // CreateBranchRepoOption options when creating a branch in a repository | ||||
@@ -249,15 +252,16 @@ type MigrateRepoOptions struct { | |||||
AuthPassword string `json:"auth_password"` | AuthPassword string `json:"auth_password"` | ||||
AuthToken string `json:"auth_token"` | AuthToken string `json:"auth_token"` | ||||
Mirror bool `json:"mirror"` | |||||
Private bool `json:"private"` | |||||
Description string `json:"description" binding:"MaxSize(255)"` | |||||
Wiki bool `json:"wiki"` | |||||
Milestones bool `json:"milestones"` | |||||
Labels bool `json:"labels"` | |||||
Issues bool `json:"issues"` | |||||
PullRequests bool `json:"pull_requests"` | |||||
Releases bool `json:"releases"` | |||||
Mirror bool `json:"mirror"` | |||||
Private bool `json:"private"` | |||||
Description string `json:"description" binding:"MaxSize(255)"` | |||||
Wiki bool `json:"wiki"` | |||||
Milestones bool `json:"milestones"` | |||||
Labels bool `json:"labels"` | |||||
Issues bool `json:"issues"` | |||||
PullRequests bool `json:"pull_requests"` | |||||
Releases bool `json:"releases"` | |||||
MirrorInterval string `json:"mirror_interval"` | |||||
} | } | ||||
// TokenAuth represents whether a service type supports token-based auth | // TokenAuth represents whether a service type supports token-based auth | ||||
@@ -141,6 +141,7 @@ func Migrate(ctx *context.APIContext, form api.MigrateRepoOptions) { | |||||
PullRequests: form.PullRequests, | PullRequests: form.PullRequests, | ||||
Releases: form.Releases, | Releases: form.Releases, | ||||
GitServiceType: gitServiceType, | GitServiceType: gitServiceType, | ||||
MirrorInterval: form.MirrorInterval, | |||||
} | } | ||||
if opts.Mirror { | if opts.Mirror { | ||||
opts.Issues = false | opts.Issues = false | ||||
@@ -9,6 +9,7 @@ import ( | |||||
"fmt" | "fmt" | ||||
"net/http" | "net/http" | ||||
"strings" | "strings" | ||||
"time" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
@@ -501,6 +502,12 @@ func Edit(ctx *context.APIContext, opts api.EditRepoOption) { | |||||
} | } | ||||
} | } | ||||
if opts.MirrorInterval != nil { | |||||
if err := updateMirrorInterval(ctx, opts); err != nil { | |||||
return | |||||
} | |||||
} | |||||
ctx.JSON(http.StatusOK, convert.ToRepo(ctx.Repo.Repository, ctx.Repo.AccessMode)) | ctx.JSON(http.StatusOK, convert.ToRepo(ctx.Repo.Repository, ctx.Repo.AccessMode)) | ||||
} | } | ||||
@@ -783,6 +790,38 @@ func updateRepoArchivedState(ctx *context.APIContext, opts api.EditRepoOption) e | |||||
return nil | return nil | ||||
} | } | ||||
// updateMirrorInterval updates the repo's mirror Interval | |||||
func updateMirrorInterval(ctx *context.APIContext, opts api.EditRepoOption) error { | |||||
repo := ctx.Repo.Repository | |||||
if opts.MirrorInterval != nil { | |||||
if !repo.IsMirror { | |||||
err := fmt.Errorf("repo is not a mirror, can not change mirror interval") | |||||
ctx.Error(http.StatusUnprocessableEntity, err.Error(), err) | |||||
return err | |||||
} | |||||
if err := repo.GetMirror(); err != nil { | |||||
log.Error("Failed to get mirror: %s", err) | |||||
ctx.Error(http.StatusInternalServerError, "MirrorInterval", err) | |||||
return err | |||||
} | |||||
if interval, err := time.ParseDuration(*opts.MirrorInterval); err == nil { | |||||
repo.Mirror.Interval = interval | |||||
if err := models.UpdateMirror(repo.Mirror); err != nil { | |||||
log.Error("Failed to Set Mirror Interval: %s", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "MirrorInterval", err) | |||||
return err | |||||
} | |||||
log.Trace("Repository %s/%s Mirror Interval was Updated to %s", ctx.Repo.Owner.Name, repo.Name, interval) | |||||
} else { | |||||
log.Error("Wrong format for MirrorInternal Sent: %s", err) | |||||
ctx.Error(http.StatusUnprocessableEntity, "MirrorInterval", err) | |||||
return err | |||||
} | |||||
} | |||||
return nil | |||||
} | |||||
// Delete one repository | // Delete one repository | ||||
func Delete(ctx *context.APIContext) { | func Delete(ctx *context.APIContext) { | ||||
// swagger:operation DELETE /repos/{owner}/{repo} repository repoDelete | // swagger:operation DELETE /repos/{owner}/{repo} repository repoDelete | ||||
@@ -13263,6 +13263,11 @@ | |||||
"internal_tracker": { | "internal_tracker": { | ||||
"$ref": "#/definitions/InternalTracker" | "$ref": "#/definitions/InternalTracker" | ||||
}, | }, | ||||
"mirror_interval": { | |||||
"description": "set to a string like `8h30m0s` to set the mirror interval time", | |||||
"type": "string", | |||||
"x-go-name": "MirrorInterval" | |||||
}, | |||||
"name": { | "name": { | ||||
"description": "name of the repository", | "description": "name of the repository", | ||||
"type": "string", | "type": "string", | ||||
@@ -14248,6 +14253,10 @@ | |||||
"type": "boolean", | "type": "boolean", | ||||
"x-go-name": "Mirror" | "x-go-name": "Mirror" | ||||
}, | }, | ||||
"mirror_interval": { | |||||
"type": "string", | |||||
"x-go-name": "MirrorInterval" | |||||
}, | |||||
"private": { | "private": { | ||||
"type": "boolean", | "type": "boolean", | ||||
"x-go-name": "Private" | "x-go-name": "Private" | ||||
@@ -14323,6 +14332,10 @@ | |||||
"type": "boolean", | "type": "boolean", | ||||
"x-go-name": "Mirror" | "x-go-name": "Mirror" | ||||
}, | }, | ||||
"mirror_interval": { | |||||
"type": "string", | |||||
"x-go-name": "MirrorInterval" | |||||
}, | |||||
"private": { | "private": { | ||||
"type": "boolean", | "type": "boolean", | ||||
"x-go-name": "Private" | "x-go-name": "Private" | ||||
@@ -15307,6 +15320,10 @@ | |||||
"type": "boolean", | "type": "boolean", | ||||
"x-go-name": "Mirror" | "x-go-name": "Mirror" | ||||
}, | }, | ||||
"mirror_interval": { | |||||
"type": "string", | |||||
"x-go-name": "MirrorInterval" | |||||
}, | |||||
"name": { | "name": { | ||||
"type": "string", | "type": "string", | ||||
"x-go-name": "Name" | "x-go-name": "Name" | ||||