* Fixes #2738 - /git/tags API * proper URLs * Adds function comments * Updates swagger * Removes newline from tag message * Removes trailing newline from commit message * Adds integration test * Removed debugging * Adds tests * Fixes bug where multiple tags of same commit show wrong tag name * Fix formatting * Removes unused varaible * Fix to annotated tag function names and response * Update modules/git/repo_tag.go Co-Authored-By: Lauris BH <lauris@nix.lv> * Uses TagPrefix * Changes per review, better error handling for getting tag and commit IDs * Fix to getting commit ID * Fix to getting commit ID * Fix to getting commit ID * Fix to getting commit ID
This commit is contained in:
parent
23a2ee3510
commit
8de0b0a3f0
16 changed files with 551 additions and 85 deletions
|
@ -146,8 +146,8 @@ func TestAPICreateFile(t *testing.T) {
|
||||||
var fileResponse api.FileResponse
|
var fileResponse api.FileResponse
|
||||||
DecodeJSON(t, resp, &fileResponse)
|
DecodeJSON(t, resp, &fileResponse)
|
||||||
expectedSHA := "a635aa942442ddfdba07468cf9661c08fbdf0ebf"
|
expectedSHA := "a635aa942442ddfdba07468cf9661c08fbdf0ebf"
|
||||||
expectedHTMLURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/blob/new_branch/new/file%d.txt", fileID)
|
expectedHTMLURL := fmt.Sprintf(setting.AppURL+"user2/repo1/blob/new_branch/new/file%d.txt", fileID)
|
||||||
expectedDownloadURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/raw/branch/new_branch/new/file%d.txt", fileID)
|
expectedDownloadURL := fmt.Sprintf(setting.AppURL+"user2/repo1/raw/branch/new_branch/new/file%d.txt", fileID)
|
||||||
assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA)
|
assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA)
|
||||||
assert.EqualValues(t, expectedHTMLURL, fileResponse.Content.HTMLURL)
|
assert.EqualValues(t, expectedHTMLURL, fileResponse.Content.HTMLURL)
|
||||||
assert.EqualValues(t, expectedDownloadURL, fileResponse.Content.DownloadURL)
|
assert.EqualValues(t, expectedDownloadURL, fileResponse.Content.DownloadURL)
|
||||||
|
|
|
@ -136,8 +136,8 @@ func TestAPIUpdateFile(t *testing.T) {
|
||||||
var fileResponse api.FileResponse
|
var fileResponse api.FileResponse
|
||||||
DecodeJSON(t, resp, &fileResponse)
|
DecodeJSON(t, resp, &fileResponse)
|
||||||
expectedSHA := "08bd14b2e2852529157324de9c226b3364e76136"
|
expectedSHA := "08bd14b2e2852529157324de9c226b3364e76136"
|
||||||
expectedHTMLURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/blob/new_branch/update/file%d.txt", fileID)
|
expectedHTMLURL := fmt.Sprintf(setting.AppURL+"user2/repo1/blob/new_branch/update/file%d.txt", fileID)
|
||||||
expectedDownloadURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/raw/branch/new_branch/update/file%d.txt", fileID)
|
expectedDownloadURL := fmt.Sprintf(setting.AppURL+"user2/repo1/raw/branch/new_branch/update/file%d.txt", fileID)
|
||||||
assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA)
|
assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA)
|
||||||
assert.EqualValues(t, expectedHTMLURL, fileResponse.Content.HTMLURL)
|
assert.EqualValues(t, expectedHTMLURL, fileResponse.Content.HTMLURL)
|
||||||
assert.EqualValues(t, expectedDownloadURL, fileResponse.Content.DownloadURL)
|
assert.EqualValues(t, expectedDownloadURL, fileResponse.Content.DownloadURL)
|
||||||
|
@ -155,8 +155,8 @@ func TestAPIUpdateFile(t *testing.T) {
|
||||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||||
DecodeJSON(t, resp, &fileResponse)
|
DecodeJSON(t, resp, &fileResponse)
|
||||||
expectedSHA = "08bd14b2e2852529157324de9c226b3364e76136"
|
expectedSHA = "08bd14b2e2852529157324de9c226b3364e76136"
|
||||||
expectedHTMLURL = fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/blob/master/rename/update/file%d.txt", fileID)
|
expectedHTMLURL = fmt.Sprintf(setting.AppURL+"user2/repo1/blob/master/rename/update/file%d.txt", fileID)
|
||||||
expectedDownloadURL = fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/raw/branch/master/rename/update/file%d.txt", fileID)
|
expectedDownloadURL = fmt.Sprintf(setting.AppURL+"user2/repo1/raw/branch/master/rename/update/file%d.txt", fileID)
|
||||||
assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA)
|
assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA)
|
||||||
assert.EqualValues(t, expectedHTMLURL, fileResponse.Content.HTMLURL)
|
assert.EqualValues(t, expectedHTMLURL, fileResponse.Content.HTMLURL)
|
||||||
assert.EqualValues(t, expectedDownloadURL, fileResponse.Content.DownloadURL)
|
assert.EqualValues(t, expectedDownloadURL, fileResponse.Content.DownloadURL)
|
||||||
|
|
59
integrations/api_repo_git_tags_test.go
Normal file
59
integrations/api_repo_git_tags_test.go
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package integrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAPIGitTags(t *testing.T) {
|
||||||
|
prepareTestEnv(t)
|
||||||
|
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
|
||||||
|
repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
|
||||||
|
// Login as User2.
|
||||||
|
session := loginUser(t, user.Name)
|
||||||
|
token := getTokenForLoggedInUser(t, session)
|
||||||
|
|
||||||
|
// Set up git config for the tagger
|
||||||
|
git.NewCommand("config", "user.name", user.Name).RunInDir(repo.RepoPath())
|
||||||
|
git.NewCommand("config", "user.email", user.Email).RunInDir(repo.RepoPath())
|
||||||
|
|
||||||
|
gitRepo, _ := git.OpenRepository(repo.RepoPath())
|
||||||
|
commit, _ := gitRepo.GetBranchCommit("master")
|
||||||
|
lTagName := "lightweightTag"
|
||||||
|
gitRepo.CreateTag(lTagName, commit.ID.String())
|
||||||
|
|
||||||
|
aTagName := "annotatedTag"
|
||||||
|
aTagMessage := "my annotated message"
|
||||||
|
gitRepo.CreateAnnotatedTag(aTagName, aTagMessage, commit.ID.String())
|
||||||
|
aTag, _ := gitRepo.GetTag(aTagName)
|
||||||
|
|
||||||
|
// SHOULD work for annotated tags
|
||||||
|
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/git/tags/%s?token=%s", user.Name, repo.Name, aTag.ID.String(), token)
|
||||||
|
res := session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
var tag *api.AnnotatedTag
|
||||||
|
DecodeJSON(t, res, &tag)
|
||||||
|
|
||||||
|
assert.Equal(t, aTagName, tag.Tag)
|
||||||
|
assert.Equal(t, aTag.ID.String(), tag.SHA)
|
||||||
|
assert.Equal(t, commit.ID.String(), tag.Object.SHA)
|
||||||
|
assert.Equal(t, aTagMessage, tag.Message)
|
||||||
|
assert.Equal(t, user.Name, tag.Tagger.Name)
|
||||||
|
assert.Equal(t, user.Email, tag.Tagger.Email)
|
||||||
|
assert.Equal(t, util.URLJoin(repo.APIURL(), "git/tags", aTag.ID.String()), tag.URL)
|
||||||
|
|
||||||
|
// Should NOT work for lightweight tags
|
||||||
|
badReq := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/git/tags/%s?token=%s", user.Name, repo.Name, commit.ID.String(), token)
|
||||||
|
session.MakeRequest(t, badReq, http.StatusBadRequest)
|
||||||
|
}
|
|
@ -6,7 +6,6 @@ package integrations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
@ -32,7 +31,7 @@ func TestAPIReposGetTags(t *testing.T) {
|
||||||
assert.EqualValues(t, 1, len(tags))
|
assert.EqualValues(t, 1, len(tags))
|
||||||
assert.Equal(t, "v1.1", tags[0].Name)
|
assert.Equal(t, "v1.1", tags[0].Name)
|
||||||
assert.Equal(t, "65f1bf27bc3bf70f64657658635e66094edbcb4d", tags[0].Commit.SHA)
|
assert.Equal(t, "65f1bf27bc3bf70f64657658635e66094edbcb4d", tags[0].Commit.SHA)
|
||||||
assert.Equal(t, path.Join(setting.AppSubURL, "/user2/repo1/commit/65f1bf27bc3bf70f64657658635e66094edbcb4d"), tags[0].Commit.URL)
|
assert.Equal(t, setting.AppURL+"api/v1/repos/user2/repo1/git/commits/65f1bf27bc3bf70f64657658635e66094edbcb4d", tags[0].Commit.URL)
|
||||||
assert.Equal(t, path.Join(setting.AppSubURL, "/user2/repo1/archive/v1.1.zip"), tags[0].ZipballURL)
|
assert.Equal(t, setting.AppURL+"user2/repo1/archive/v1.1.zip", tags[0].ZipballURL)
|
||||||
assert.Equal(t, path.Join(setting.AppSubURL, "/user2/repo1/archive/v1.1.tar.gz"), tags[0].TarballURL)
|
assert.Equal(t, setting.AppURL+"user2/repo1/archive/v1.1.tar.gz", tags[0].TarballURL)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetTagsByPath returns repo tags by it's path
|
// GetTagsByPath returns repo tags by its path
|
||||||
func GetTagsByPath(path string) ([]*git.Tag, error) {
|
func GetTagsByPath(path string) ([]*git.Tag, error) {
|
||||||
gitRepo, err := git.OpenRepository(path)
|
gitRepo, err := git.OpenRepository(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -31,15 +31,19 @@ func (repo *Repository) GetRefsFiltered(pattern string) ([]*Reference, error) {
|
||||||
if err = refsIter.ForEach(func(ref *plumbing.Reference) error {
|
if err = refsIter.ForEach(func(ref *plumbing.Reference) error {
|
||||||
if ref.Name() != plumbing.HEAD && !ref.Name().IsRemote() &&
|
if ref.Name() != plumbing.HEAD && !ref.Name().IsRemote() &&
|
||||||
(pattern == "" || strings.HasPrefix(ref.Name().String(), pattern)) {
|
(pattern == "" || strings.HasPrefix(ref.Name().String(), pattern)) {
|
||||||
|
refType := string(ObjectCommit)
|
||||||
|
if ref.Name().IsTag() {
|
||||||
|
// tags can be of type `commit` (lightweight) or `tag` (annotated)
|
||||||
|
if tagType, _ := repo.GetTagType(SHA1(ref.Hash())); err == nil {
|
||||||
|
refType = tagType
|
||||||
|
}
|
||||||
|
}
|
||||||
r := &Reference{
|
r := &Reference{
|
||||||
Name: ref.Name().String(),
|
Name: ref.Name().String(),
|
||||||
Object: SHA1(ref.Hash()),
|
Object: SHA1(ref.Hash()),
|
||||||
Type: string(ObjectCommit),
|
Type: refType,
|
||||||
repo: repo,
|
repo: repo,
|
||||||
}
|
}
|
||||||
if ref.Name().IsTag() {
|
|
||||||
r.Type = string(ObjectTag)
|
|
||||||
}
|
|
||||||
refs = append(refs, r)
|
refs = append(refs, r)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
package git
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mcuadros/go-version"
|
"github.com/mcuadros/go-version"
|
||||||
|
@ -35,34 +36,78 @@ func (repo *Repository) CreateTag(name, revision string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateAnnotatedTag create one annotated tag in the repository
|
||||||
|
func (repo *Repository) CreateAnnotatedTag(name, message, revision string) error {
|
||||||
|
_, err := NewCommand("tag", "-a", "-m", message, name, revision).RunInDir(repo.Path)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (repo *Repository) getTag(id SHA1) (*Tag, error) {
|
func (repo *Repository) getTag(id SHA1) (*Tag, error) {
|
||||||
t, ok := repo.tagCache.Get(id.String())
|
t, ok := repo.tagCache.Get(id.String())
|
||||||
if ok {
|
if ok {
|
||||||
log("Hit cache: %s", id)
|
log("Hit cache: %s", id)
|
||||||
return t.(*Tag), nil
|
tagClone := *t.(*Tag)
|
||||||
|
return &tagClone, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get tag type
|
// Get tag name
|
||||||
tp, err := NewCommand("cat-file", "-t", id.String()).RunInDir(repo.Path)
|
name, err := repo.GetTagNameBySHA(id.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tp = strings.TrimSpace(tp)
|
|
||||||
|
|
||||||
// Tag is a commit.
|
tp, err := repo.GetTagType(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the commit ID and tag ID (may be different for annotated tag) for the returned tag object
|
||||||
|
commitIDStr, err := repo.GetTagCommitID(name)
|
||||||
|
if err != nil {
|
||||||
|
// every tag should have a commit ID so return all errors
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
commitID, err := NewIDFromString(commitIDStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// tagID defaults to the commit ID as the tag ID and then tries to get a tag ID (only annotated tags)
|
||||||
|
tagID := commitID
|
||||||
|
if tagIDStr, err := repo.GetTagID(name); err != nil {
|
||||||
|
// if the err is NotExist then we can ignore and just keep tagID as ID (is lightweight tag)
|
||||||
|
// all other errors we return
|
||||||
|
if !IsErrNotExist(err) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tagID, err = NewIDFromString(tagIDStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If type is "commit, the tag is a lightweight tag
|
||||||
if ObjectType(tp) == ObjectCommit {
|
if ObjectType(tp) == ObjectCommit {
|
||||||
|
commit, err := repo.GetCommit(id.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
tag := &Tag{
|
tag := &Tag{
|
||||||
ID: id,
|
Name: name,
|
||||||
Object: id,
|
ID: tagID,
|
||||||
Type: string(ObjectCommit),
|
Object: commitID,
|
||||||
repo: repo,
|
Type: string(ObjectCommit),
|
||||||
|
Tagger: commit.Committer,
|
||||||
|
Message: commit.Message(),
|
||||||
|
repo: repo,
|
||||||
}
|
}
|
||||||
|
|
||||||
repo.tagCache.Set(id.String(), tag)
|
repo.tagCache.Set(id.String(), tag)
|
||||||
return tag, nil
|
return tag, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tag with message.
|
// The tag is an annotated tag with a message.
|
||||||
data, err := NewCommand("cat-file", "-p", id.String()).RunInDirBytes(repo.Path)
|
data, err := NewCommand("cat-file", "-p", id.String()).RunInDirBytes(repo.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -73,16 +118,57 @@ func (repo *Repository) getTag(id SHA1) (*Tag, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tag.Name = name
|
||||||
tag.ID = id
|
tag.ID = id
|
||||||
tag.repo = repo
|
tag.repo = repo
|
||||||
|
tag.Type = tp
|
||||||
|
|
||||||
repo.tagCache.Set(id.String(), tag)
|
repo.tagCache.Set(id.String(), tag)
|
||||||
return tag, nil
|
return tag, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTagNameBySHA returns the name of a tag from its tag object SHA or commit SHA
|
||||||
|
func (repo *Repository) GetTagNameBySHA(sha string) (string, error) {
|
||||||
|
if len(sha) < 5 {
|
||||||
|
return "", fmt.Errorf("SHA is too short: %s", sha)
|
||||||
|
}
|
||||||
|
|
||||||
|
stdout, err := NewCommand("show-ref", "--tags", "-d").RunInDir(repo.Path)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
tagRefs := strings.Split(stdout, "\n")
|
||||||
|
for _, tagRef := range tagRefs {
|
||||||
|
if len(strings.TrimSpace(tagRef)) > 0 {
|
||||||
|
fields := strings.Fields(tagRef)
|
||||||
|
if strings.HasPrefix(fields[0], sha) && strings.HasPrefix(fields[1], TagPrefix) {
|
||||||
|
name := fields[1][len(TagPrefix):]
|
||||||
|
// annotated tags show up twice, their name for commit ID is suffixed with ^{}
|
||||||
|
name = strings.TrimSuffix(name, "^{}")
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", ErrNotExist{ID: sha}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTagID returns the object ID for a tag (annotated tags have both an object SHA AND a commit SHA)
|
||||||
|
func (repo *Repository) GetTagID(name string) (string, error) {
|
||||||
|
stdout, err := NewCommand("show-ref", name).RunInDir(repo.Path)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
fields := strings.Fields(stdout)
|
||||||
|
if len(fields) != 2 {
|
||||||
|
return "", ErrNotExist{ID: name}
|
||||||
|
}
|
||||||
|
return fields[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetTag returns a Git tag by given name.
|
// GetTag returns a Git tag by given name.
|
||||||
func (repo *Repository) GetTag(name string) (*Tag, error) {
|
func (repo *Repository) GetTag(name string) (*Tag, error) {
|
||||||
idStr, err := repo.GetTagCommitID(name)
|
idStr, err := repo.GetTagID(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -96,7 +182,6 @@ func (repo *Repository) GetTag(name string) (*Tag, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tag.Name = name
|
|
||||||
return tag, nil
|
return tag, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +193,7 @@ func (repo *Repository) GetTagInfos() ([]*Tag, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tagNames := strings.Split(stdout, "\n")
|
tagNames := strings.Split(strings.TrimRight(stdout, "\n"), "\n")
|
||||||
var tags = make([]*Tag, 0, len(tagNames))
|
var tags = make([]*Tag, 0, len(tagNames))
|
||||||
for _, tagName := range tagNames {
|
for _, tagName := range tagNames {
|
||||||
tagName = strings.TrimSpace(tagName)
|
tagName = strings.TrimSpace(tagName)
|
||||||
|
@ -120,6 +205,7 @@ func (repo *Repository) GetTagInfos() ([]*Tag, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
tag.Name = tagName
|
||||||
tags = append(tags, tag)
|
tags = append(tags, tag)
|
||||||
}
|
}
|
||||||
sortTagsByTime(tags)
|
sortTagsByTime(tags)
|
||||||
|
@ -150,3 +236,38 @@ func (repo *Repository) GetTags() ([]string, error) {
|
||||||
|
|
||||||
return tagNames, nil
|
return tagNames, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTagType gets the type of the tag, either commit (simple) or tag (annotated)
|
||||||
|
func (repo *Repository) GetTagType(id SHA1) (string, error) {
|
||||||
|
// Get tag type
|
||||||
|
stdout, err := NewCommand("cat-file", "-t", id.String()).RunInDir(repo.Path)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if len(stdout) == 0 {
|
||||||
|
return "", ErrNotExist{ID: id.String()}
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(stdout), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAnnotatedTag returns a Git tag by its SHA, must be an annotated tag
|
||||||
|
func (repo *Repository) GetAnnotatedTag(sha string) (*Tag, error) {
|
||||||
|
id, err := NewIDFromString(sha)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tag type must be "tag" (annotated) and not a "commit" (lightweight) tag
|
||||||
|
if tagType, err := repo.GetTagType(id); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if ObjectType(tagType) != ObjectTag {
|
||||||
|
// not an annotated tag
|
||||||
|
return nil, ErrNotExist{ID: id.String()}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag, err := repo.getTag(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tag, nil
|
||||||
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@ func TestRepository_GetTags(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, tags, 1)
|
assert.Len(t, tags, 1)
|
||||||
assert.EqualValues(t, "test", tags[0].Name)
|
assert.EqualValues(t, "test", tags[0].Name)
|
||||||
assert.EqualValues(t, "37991dec2c8e592043f47155ce4808d4580f9123", tags[0].ID.String())
|
assert.EqualValues(t, "3ad28a9149a2864384548f3d17ed7f38014c9e8a", tags[0].ID.String())
|
||||||
assert.EqualValues(t, "commit", tags[0].Type)
|
assert.EqualValues(t, "tag", tags[0].Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRepository_GetTag(t *testing.T) {
|
func TestRepository_GetTag(t *testing.T) {
|
||||||
|
@ -35,10 +35,78 @@ func TestRepository_GetTag(t *testing.T) {
|
||||||
bareRepo1, err := OpenRepository(clonedPath)
|
bareRepo1, err := OpenRepository(clonedPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
tag, err := bareRepo1.GetTag("test")
|
lTagCommitID := "6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1"
|
||||||
|
lTagName := "lightweightTag"
|
||||||
|
bareRepo1.CreateTag(lTagName, lTagCommitID)
|
||||||
|
|
||||||
|
aTagCommitID := "8006ff9adbf0cb94da7dad9e537e53817f9fa5c0"
|
||||||
|
aTagName := "annotatedTag"
|
||||||
|
aTagMessage := "my annotated message"
|
||||||
|
bareRepo1.CreateAnnotatedTag(aTagName, aTagMessage, aTagCommitID)
|
||||||
|
aTagID, _ := bareRepo1.GetTagID(aTagName)
|
||||||
|
|
||||||
|
lTag, err := bareRepo1.GetTag(lTagName)
|
||||||
|
lTag.repo = nil
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, lTag)
|
||||||
|
assert.EqualValues(t, lTagName, lTag.Name)
|
||||||
|
assert.EqualValues(t, lTagCommitID, lTag.ID.String())
|
||||||
|
assert.EqualValues(t, lTagCommitID, lTag.Object.String())
|
||||||
|
assert.EqualValues(t, "commit", lTag.Type)
|
||||||
|
|
||||||
|
aTag, err := bareRepo1.GetTag(aTagName)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, aTag)
|
||||||
|
assert.EqualValues(t, aTagName, aTag.Name)
|
||||||
|
assert.EqualValues(t, aTagID, aTag.ID.String())
|
||||||
|
assert.NotEqual(t, aTagID, aTag.Object.String())
|
||||||
|
assert.EqualValues(t, aTagCommitID, aTag.Object.String())
|
||||||
|
assert.EqualValues(t, "tag", aTag.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRepository_GetAnnotatedTag(t *testing.T) {
|
||||||
|
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
|
||||||
|
|
||||||
|
clonedPath, err := cloneRepo(bareRepo1Path, testReposDir, "repo1_TestRepository_GetTag")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer os.RemoveAll(clonedPath)
|
||||||
|
|
||||||
|
bareRepo1, err := OpenRepository(clonedPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
lTagCommitID := "6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1"
|
||||||
|
lTagName := "lightweightTag"
|
||||||
|
bareRepo1.CreateTag(lTagName, lTagCommitID)
|
||||||
|
|
||||||
|
aTagCommitID := "8006ff9adbf0cb94da7dad9e537e53817f9fa5c0"
|
||||||
|
aTagName := "annotatedTag"
|
||||||
|
aTagMessage := "my annotated message"
|
||||||
|
bareRepo1.CreateAnnotatedTag(aTagName, aTagMessage, aTagCommitID)
|
||||||
|
aTagID, _ := bareRepo1.GetTagID(aTagName)
|
||||||
|
|
||||||
|
// Try an annotated tag
|
||||||
|
tag, err := bareRepo1.GetAnnotatedTag(aTagID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, tag)
|
assert.NotNil(t, tag)
|
||||||
assert.EqualValues(t, "test", tag.Name)
|
assert.EqualValues(t, aTagName, tag.Name)
|
||||||
assert.EqualValues(t, "37991dec2c8e592043f47155ce4808d4580f9123", tag.ID.String())
|
assert.EqualValues(t, aTagID, tag.ID.String())
|
||||||
assert.EqualValues(t, "commit", tag.Type)
|
assert.EqualValues(t, "tag", tag.Type)
|
||||||
|
|
||||||
|
// Annotated tag's Commit ID should fail
|
||||||
|
tag2, err := bareRepo1.GetAnnotatedTag(aTagCommitID)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.True(t, IsErrNotExist(err))
|
||||||
|
assert.Nil(t, tag2)
|
||||||
|
|
||||||
|
// Annotated tag's name should fail
|
||||||
|
tag3, err := bareRepo1.GetAnnotatedTag(aTagName)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Errorf(t, err, "Length must be 40: %d", len(aTagName))
|
||||||
|
assert.Nil(t, tag3)
|
||||||
|
|
||||||
|
// Lightweight Tag should fail
|
||||||
|
tag4, err := bareRepo1.GetAnnotatedTag(lTagCommitID)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.True(t, IsErrNotExist(err))
|
||||||
|
assert.Nil(t, tag4)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ package git
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Tag represents a Git tag.
|
// Tag represents a Git tag.
|
||||||
|
@ -59,7 +60,7 @@ l:
|
||||||
}
|
}
|
||||||
nextline += eol + 1
|
nextline += eol + 1
|
||||||
case eol == 0:
|
case eol == 0:
|
||||||
tag.Message = string(data[nextline+1:])
|
tag.Message = strings.TrimRight(string(data[nextline+1:]), "\n")
|
||||||
break l
|
break l
|
||||||
default:
|
default:
|
||||||
break l
|
break l
|
||||||
|
|
|
@ -6,11 +6,27 @@ package structs
|
||||||
|
|
||||||
// Tag represents a repository tag
|
// Tag represents a repository tag
|
||||||
type Tag struct {
|
type Tag struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Commit struct {
|
ID string `json:"id"`
|
||||||
SHA string `json:"sha"`
|
Commit *CommitMeta `json:"commit"`
|
||||||
URL string `json:"url"`
|
ZipballURL string `json:"zipball_url"`
|
||||||
} `json:"commit"`
|
TarballURL string `json:"tarball_url"`
|
||||||
ZipballURL string `json:"zipball_url"`
|
}
|
||||||
TarballURL string `json:"tarball_url"`
|
|
||||||
|
// AnnotatedTag represents an annotated tag
|
||||||
|
type AnnotatedTag struct {
|
||||||
|
Tag string `json:"tag"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Tagger *CommitUser `json:"tagger"`
|
||||||
|
Object *AnnotatedTagObject `json:"object"`
|
||||||
|
Verification *PayloadCommitVerification `json:"verification"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnnotatedTagObject contains meta information of the tag object
|
||||||
|
type AnnotatedTagObject struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -751,6 +751,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||||
Post(reqToken(), bind(api.CreateStatusOption{}), repo.NewCommitStatus)
|
Post(reqToken(), bind(api.CreateStatusOption{}), repo.NewCommitStatus)
|
||||||
}, reqRepoReader(models.UnitTypeCode))
|
}, reqRepoReader(models.UnitTypeCode))
|
||||||
m.Group("/commits/:ref", func() {
|
m.Group("/commits/:ref", func() {
|
||||||
|
// TODO: Add m.Get("") for single commit (https://developer.github.com/v3/repos/commits/#get-a-single-commit)
|
||||||
m.Get("/status", repo.GetCombinedCommitStatusByRef)
|
m.Get("/status", repo.GetCombinedCommitStatusByRef)
|
||||||
m.Get("/statuses", repo.GetCommitStatusesByRef)
|
m.Get("/statuses", repo.GetCommitStatusesByRef)
|
||||||
}, reqRepoReader(models.UnitTypeCode))
|
}, reqRepoReader(models.UnitTypeCode))
|
||||||
|
@ -762,6 +763,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||||
m.Get("/refs/*", repo.GetGitRefs)
|
m.Get("/refs/*", repo.GetGitRefs)
|
||||||
m.Get("/trees/:sha", context.RepoRef(), repo.GetTree)
|
m.Get("/trees/:sha", context.RepoRef(), repo.GetTree)
|
||||||
m.Get("/blobs/:sha", context.RepoRef(), repo.GetBlob)
|
m.Get("/blobs/:sha", context.RepoRef(), repo.GetBlob)
|
||||||
|
m.Get("/tags/:sha", context.RepoRef(), repo.GetTag)
|
||||||
}, reqRepoReader(models.UnitTypeCode))
|
}, reqRepoReader(models.UnitTypeCode))
|
||||||
m.Group("/contents", func() {
|
m.Group("/contents", func() {
|
||||||
m.Get("/*", repo.GetFileContents)
|
m.Get("/*", repo.GetFileContents)
|
||||||
|
|
|
@ -6,6 +6,7 @@ package convert
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
@ -26,7 +27,7 @@ func ToEmail(email *models.EmailAddress) *api.Email {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToBranch convert a commit and branch to an api.Branch
|
// ToBranch convert a git.Commit and git.Branch to an api.Branch
|
||||||
func ToBranch(repo *models.Repository, b *git.Branch, c *git.Commit) *api.Branch {
|
func ToBranch(repo *models.Repository, b *git.Branch, c *git.Commit) *api.Branch {
|
||||||
return &api.Branch{
|
return &api.Branch{
|
||||||
Name: b.Name,
|
Name: b.Name,
|
||||||
|
@ -34,23 +35,18 @@ func ToBranch(repo *models.Repository, b *git.Branch, c *git.Commit) *api.Branch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToTag convert a tag to an api.Tag
|
// ToTag convert a git.Tag to an api.Tag
|
||||||
func ToTag(repo *models.Repository, t *git.Tag) *api.Tag {
|
func ToTag(repo *models.Repository, t *git.Tag) *api.Tag {
|
||||||
return &api.Tag{
|
return &api.Tag{
|
||||||
Name: t.Name,
|
Name: t.Name,
|
||||||
Commit: struct {
|
ID: t.ID.String(),
|
||||||
SHA string `json:"sha"`
|
Commit: ToCommitMeta(repo, t),
|
||||||
URL string `json:"url"`
|
ZipballURL: util.URLJoin(repo.HTMLURL(), "archive", t.Name+".zip"),
|
||||||
}{
|
TarballURL: util.URLJoin(repo.HTMLURL(), "archive", t.Name+".tar.gz"),
|
||||||
SHA: t.ID.String(),
|
|
||||||
URL: util.URLJoin(repo.Link(), "commit", t.ID.String()),
|
|
||||||
},
|
|
||||||
ZipballURL: util.URLJoin(repo.Link(), "archive", t.Name+".zip"),
|
|
||||||
TarballURL: util.URLJoin(repo.Link(), "archive", t.Name+".tar.gz"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToCommit convert a commit to api.PayloadCommit
|
// ToCommit convert a git.Commit to api.PayloadCommit
|
||||||
func ToCommit(repo *models.Repository, c *git.Commit) *api.PayloadCommit {
|
func ToCommit(repo *models.Repository, c *git.Commit) *api.PayloadCommit {
|
||||||
authorUsername := ""
|
authorUsername := ""
|
||||||
if author, err := models.GetUserByEmail(c.Author.Email); err == nil {
|
if author, err := models.GetUserByEmail(c.Author.Email); err == nil {
|
||||||
|
@ -66,17 +62,10 @@ func ToCommit(repo *models.Repository, c *git.Commit) *api.PayloadCommit {
|
||||||
log.Error("GetUserByEmail: %v", err)
|
log.Error("GetUserByEmail: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
verif := models.ParseCommitWithSignature(c)
|
|
||||||
var signature, payload string
|
|
||||||
if c.Signature != nil {
|
|
||||||
signature = c.Signature.Signature
|
|
||||||
payload = c.Signature.Payload
|
|
||||||
}
|
|
||||||
|
|
||||||
return &api.PayloadCommit{
|
return &api.PayloadCommit{
|
||||||
ID: c.ID.String(),
|
ID: c.ID.String(),
|
||||||
Message: c.Message(),
|
Message: c.Message(),
|
||||||
URL: util.URLJoin(repo.Link(), "commit", c.ID.String()),
|
URL: util.URLJoin(repo.HTMLURL(), "commit", c.ID.String()),
|
||||||
Author: &api.PayloadUser{
|
Author: &api.PayloadUser{
|
||||||
Name: c.Author.Name,
|
Name: c.Author.Name,
|
||||||
Email: c.Author.Email,
|
Email: c.Author.Email,
|
||||||
|
@ -87,13 +76,24 @@ func ToCommit(repo *models.Repository, c *git.Commit) *api.PayloadCommit {
|
||||||
Email: c.Committer.Email,
|
Email: c.Committer.Email,
|
||||||
UserName: committerUsername,
|
UserName: committerUsername,
|
||||||
},
|
},
|
||||||
Timestamp: c.Author.When,
|
Timestamp: c.Author.When,
|
||||||
Verification: &api.PayloadCommitVerification{
|
Verification: ToVerification(c),
|
||||||
Verified: verif.Verified,
|
}
|
||||||
Reason: verif.Reason,
|
}
|
||||||
Signature: signature,
|
|
||||||
Payload: payload,
|
// ToVerification convert a git.Commit.Signature to an api.PayloadCommitVerification
|
||||||
},
|
func ToVerification(c *git.Commit) *api.PayloadCommitVerification {
|
||||||
|
verif := models.ParseCommitWithSignature(c)
|
||||||
|
var signature, payload string
|
||||||
|
if c.Signature != nil {
|
||||||
|
signature = c.Signature.Signature
|
||||||
|
payload = c.Signature.Payload
|
||||||
|
}
|
||||||
|
return &api.PayloadCommitVerification{
|
||||||
|
Verified: verif.Verified,
|
||||||
|
Reason: verif.Reason,
|
||||||
|
Signature: signature,
|
||||||
|
Payload: payload,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,3 +242,45 @@ func ToUser(user *models.User, signed, admin bool) *api.User {
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToAnnotatedTag convert git.Tag to api.AnnotatedTag
|
||||||
|
func ToAnnotatedTag(repo *models.Repository, t *git.Tag, c *git.Commit) *api.AnnotatedTag {
|
||||||
|
return &api.AnnotatedTag{
|
||||||
|
Tag: t.Name,
|
||||||
|
SHA: t.ID.String(),
|
||||||
|
Object: ToAnnotatedTagObject(repo, c),
|
||||||
|
Message: t.Message,
|
||||||
|
URL: util.URLJoin(repo.APIURL(), "git/tags", t.ID.String()),
|
||||||
|
Tagger: ToCommitUser(t.Tagger),
|
||||||
|
Verification: ToVerification(c),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToAnnotatedTagObject convert a git.Commit to an api.AnnotatedTagObject
|
||||||
|
func ToAnnotatedTagObject(repo *models.Repository, commit *git.Commit) *api.AnnotatedTagObject {
|
||||||
|
return &api.AnnotatedTagObject{
|
||||||
|
SHA: commit.ID.String(),
|
||||||
|
Type: string(git.ObjectCommit),
|
||||||
|
URL: util.URLJoin(repo.APIURL(), "git/commits", commit.ID.String()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToCommitUser convert a git.Signature to an api.CommitUser
|
||||||
|
func ToCommitUser(sig *git.Signature) *api.CommitUser {
|
||||||
|
return &api.CommitUser{
|
||||||
|
Identity: api.Identity{
|
||||||
|
Name: sig.Name,
|
||||||
|
Email: sig.Email,
|
||||||
|
},
|
||||||
|
Date: sig.When.UTC().Format(time.RFC3339),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToCommitMeta convert a git.Tag to an api.CommitMeta
|
||||||
|
func ToCommitMeta(repo *models.Repository, tag *git.Tag) *api.CommitMeta {
|
||||||
|
return &api.CommitMeta{
|
||||||
|
SHA: tag.ID.String(),
|
||||||
|
// TODO: Add the /commits API endpoint and use it here (https://developer.github.com/v3/repos/commits/#get-a-single-commit)
|
||||||
|
URL: util.URLJoin(repo.APIURL(), "git/commits", tag.ID.String()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -100,8 +100,7 @@ func getGitRefsInternal(ctx *context.APIContext, filter string) {
|
||||||
Object: &api.GitObject{
|
Object: &api.GitObject{
|
||||||
SHA: refs[i].Object.String(),
|
SHA: refs[i].Object.String(),
|
||||||
Type: refs[i].Type,
|
Type: refs[i].Type,
|
||||||
// TODO: Add commit/tag info URL
|
URL: ctx.Repo.Repository.APIURL() + "/git/" + refs[i].Type + "s/" + refs[i].Object.String(),
|
||||||
//URL: ctx.Repo.Repository.APIURL() + "/git/" + refs[i].Type + "s/" + refs[i].Object.String(),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ package repo
|
||||||
import (
|
import (
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/routers/api/v1/convert"
|
"code.gitea.io/gitea/routers/api/v1/convert"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
)
|
)
|
||||||
|
@ -45,3 +46,47 @@ func ListTags(ctx *context.APIContext) {
|
||||||
|
|
||||||
ctx.JSON(200, &apiTags)
|
ctx.JSON(200, &apiTags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTag get the tag of a repository.
|
||||||
|
func GetTag(ctx *context.APIContext) {
|
||||||
|
// swagger:operation GET /repos/{owner}/{repo}/git/tags/{sha} repository GetTag
|
||||||
|
// ---
|
||||||
|
// summary: Gets the tag of a repository.
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: owner
|
||||||
|
// in: path
|
||||||
|
// description: owner of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: repo
|
||||||
|
// in: path
|
||||||
|
// description: name of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: sha
|
||||||
|
// in: path
|
||||||
|
// description: sha of the tag
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// responses:
|
||||||
|
// "200":
|
||||||
|
// "$ref": "#/responses/AnnotatedTag"
|
||||||
|
|
||||||
|
sha := ctx.Params("sha")
|
||||||
|
if len(sha) == 0 {
|
||||||
|
ctx.Error(http.StatusBadRequest, "", "SHA not provided")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if tag, err := ctx.Repo.GitRepo.GetAnnotatedTag(sha); err != nil {
|
||||||
|
ctx.Error(http.StatusBadRequest, "GetTag", err)
|
||||||
|
} else {
|
||||||
|
commit, err := tag.Commit()
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusBadRequest, "GetTag", err)
|
||||||
|
}
|
||||||
|
ctx.JSON(http.StatusOK, convert.ToAnnotatedTag(ctx.Repo.Repository, tag, commit))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -38,11 +38,25 @@ type swaggerResponseBranchList struct {
|
||||||
|
|
||||||
// TagList
|
// TagList
|
||||||
// swagger:response TagList
|
// swagger:response TagList
|
||||||
type swaggerReponseTagList struct {
|
type swaggerResponseTagList struct {
|
||||||
// in:body
|
// in:body
|
||||||
Body []api.Tag `json:"body"`
|
Body []api.Tag `json:"body"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tag
|
||||||
|
// swagger:response Tag
|
||||||
|
type swaggerResponseTag struct {
|
||||||
|
// in:body
|
||||||
|
Body api.Tag `json:"body"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnnotatedTag
|
||||||
|
// swagger:response AnnotatedTag
|
||||||
|
type swaggerResponseAnnotatedTag struct {
|
||||||
|
// in:body
|
||||||
|
Body api.AnnotatedTag `json:"body"`
|
||||||
|
}
|
||||||
|
|
||||||
// Reference
|
// Reference
|
||||||
// swagger:response Reference
|
// swagger:response Reference
|
||||||
type swaggerResponseReference struct {
|
type swaggerResponseReference struct {
|
||||||
|
|
|
@ -2036,6 +2036,46 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/repos/{owner}/{repo}/git/tags/{sha}": {
|
||||||
|
"get": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"repository"
|
||||||
|
],
|
||||||
|
"summary": "Gets the tag of a repository.",
|
||||||
|
"operationId": "GetTag",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "owner of the repo",
|
||||||
|
"name": "owner",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the repo",
|
||||||
|
"name": "repo",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "sha of the tag",
|
||||||
|
"name": "sha",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"$ref": "#/responses/AnnotatedTag"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/repos/{owner}/{repo}/git/trees/{sha}": {
|
"/repos/{owner}/{repo}/git/trees/{sha}": {
|
||||||
"get": {
|
"get": {
|
||||||
"produces": [
|
"produces": [
|
||||||
|
@ -6762,6 +6802,57 @@
|
||||||
},
|
},
|
||||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
},
|
},
|
||||||
|
"AnnotatedTag": {
|
||||||
|
"description": "AnnotatedTag represents an annotated tag",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "Message"
|
||||||
|
},
|
||||||
|
"object": {
|
||||||
|
"$ref": "#/definitions/AnnotatedTagObject"
|
||||||
|
},
|
||||||
|
"sha": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "SHA"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "Tag"
|
||||||
|
},
|
||||||
|
"tagger": {
|
||||||
|
"$ref": "#/definitions/CommitUser"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "URL"
|
||||||
|
},
|
||||||
|
"verification": {
|
||||||
|
"$ref": "#/definitions/PayloadCommitVerification"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
|
},
|
||||||
|
"AnnotatedTagObject": {
|
||||||
|
"description": "AnnotatedTagObject contains meta information of the tag object",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"sha": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "SHA"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "Type"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "URL"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
|
},
|
||||||
"Attachment": {
|
"Attachment": {
|
||||||
"description": "Attachment a generic attachment",
|
"description": "Attachment a generic attachment",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -9458,18 +9549,11 @@
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"commit": {
|
"commit": {
|
||||||
"type": "object",
|
"$ref": "#/definitions/CommitMeta"
|
||||||
"properties": {
|
},
|
||||||
"sha": {
|
"id": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "SHA"
|
"x-go-name": "ID"
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"type": "string",
|
|
||||||
"x-go-name": "URL"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"x-go-name": "Commit"
|
|
||||||
},
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -9735,6 +9819,12 @@
|
||||||
"AccessTokenList": {
|
"AccessTokenList": {
|
||||||
"description": "AccessTokenList represents a list of API access token."
|
"description": "AccessTokenList represents a list of API access token."
|
||||||
},
|
},
|
||||||
|
"AnnotatedTag": {
|
||||||
|
"description": "AnnotatedTag",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/AnnotatedTag"
|
||||||
|
}
|
||||||
|
},
|
||||||
"Attachment": {
|
"Attachment": {
|
||||||
"description": "Attachment",
|
"description": "Attachment",
|
||||||
"schema": {
|
"schema": {
|
||||||
|
@ -10056,6 +10146,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Tag": {
|
||||||
|
"description": "Tag",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/Tag"
|
||||||
|
}
|
||||||
|
},
|
||||||
"TagList": {
|
"TagList": {
|
||||||
"description": "TagList",
|
"description": "TagList",
|
||||||
"schema": {
|
"schema": {
|
||||||
|
|
Reference in a new issue