Add MirrorInterval to the API (#14163)
* 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>
This commit is contained in:
		
							parent
							
								
									3abea9e9eb
								
							
						
					
					
						commit
						7576e37a65
					
				
					 10 changed files with 115 additions and 21 deletions
				
			
		|  | @ -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)"` | 	RepoName       string `json:"repo_name" binding:"Required;AlphaDashDot;MaxSize(100)"` | ||||||
| 	Mirror       bool   `json:"mirror"` | 	Mirror         bool   `json:"mirror"` | ||||||
| 	Private      bool   `json:"private"` | 	Private        bool   `json:"private"` | ||||||
| 	Description  string `json:"description" binding:"MaxSize(255)"` | 	Description    string `json:"description" binding:"MaxSize(255)"` | ||||||
| 	Wiki         bool   `json:"wiki"` | 	Wiki           bool   `json:"wiki"` | ||||||
| 	Milestones   bool   `json:"milestones"` | 	Milestones     bool   `json:"milestones"` | ||||||
| 	Labels       bool   `json:"labels"` | 	Labels         bool   `json:"labels"` | ||||||
| 	Issues       bool   `json:"issues"` | 	Issues         bool   `json:"issues"` | ||||||
| 	PullRequests bool   `json:"pull_requests"` | 	PullRequests   bool   `json:"pull_requests"` | ||||||
| 	Releases     bool   `json:"releases"` | 	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"` | 	Mirror         bool   `json:"mirror"` | ||||||
| 	Private      bool   `json:"private"` | 	Private        bool   `json:"private"` | ||||||
| 	Description  string `json:"description" binding:"MaxSize(255)"` | 	Description    string `json:"description" binding:"MaxSize(255)"` | ||||||
| 	Wiki         bool   `json:"wiki"` | 	Wiki           bool   `json:"wiki"` | ||||||
| 	Milestones   bool   `json:"milestones"` | 	Milestones     bool   `json:"milestones"` | ||||||
| 	Labels       bool   `json:"labels"` | 	Labels         bool   `json:"labels"` | ||||||
| 	Issues       bool   `json:"issues"` | 	Issues         bool   `json:"issues"` | ||||||
| 	PullRequests bool   `json:"pull_requests"` | 	PullRequests   bool   `json:"pull_requests"` | ||||||
| 	Releases     bool   `json:"releases"` | 	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" | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue