Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variable expansion in repository templates #9163

Merged
merged 21 commits into from
Nov 30, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 0 additions & 48 deletions models/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -1360,54 +1360,6 @@ func prepareRepoCommit(e Engine, repo *Repository, tmpDir, repoPath string, opts
return nil
}

func generateRepoCommit(e Engine, repo, templateRepo *Repository, tmpDir string) error {
commitTimeStr := time.Now().Format(time.RFC3339)
authorSig := repo.Owner.NewGitSig()

// Because this may call hooks we should pass in the environment
env := append(os.Environ(),
"GIT_AUTHOR_NAME="+authorSig.Name,
"GIT_AUTHOR_EMAIL="+authorSig.Email,
"GIT_AUTHOR_DATE="+commitTimeStr,
"GIT_COMMITTER_NAME="+authorSig.Name,
"GIT_COMMITTER_EMAIL="+authorSig.Email,
"GIT_COMMITTER_DATE="+commitTimeStr,
)

// Clone to temporary path and do the init commit.
templateRepoPath := templateRepo.repoPath(e)
_, stderr, err := process.GetManager().ExecDirEnv(
-1, "",
fmt.Sprintf("generateRepoCommit(git clone): %s", templateRepoPath),
env,
git.GitExecutable, "clone", "--depth", "1", templateRepoPath, tmpDir,
)
if err != nil {
return fmt.Errorf("git clone: %v - %s", err, stderr)
}

if err := os.RemoveAll(path.Join(tmpDir, ".git")); err != nil {
return fmt.Errorf("remove git dir: %v", err)
}

if err := git.InitRepository(tmpDir, false); err != nil {
return err
}

repoPath := repo.repoPath(e)
_, stderr, err = process.GetManager().ExecDirEnv(
-1, tmpDir,
fmt.Sprintf("generateRepoCommit(git remote add): %s", repoPath),
env,
git.GitExecutable, "remote", "add", "origin", repoPath,
)
if err != nil {
return fmt.Errorf("git remote add: %v - %s", err, stderr)
}

return initRepoCommit(tmpDir, repo.Owner)
}

func checkInitRepository(repoPath string) (err error) {
// Somehow the directory could exist.
if com.IsExist(repoPath) {
Expand Down
123 changes: 119 additions & 4 deletions models/repo_generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
package models

import (
"code.gitea.io/gitea/modules/process"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"strconv"
"strings"
Expand Down Expand Up @@ -36,8 +39,91 @@ func (gro GenerateRepoOptions) IsValid() bool {
return gro.GitContent || gro.Topics || gro.GitHooks || gro.Webhooks || gro.Avatar || gro.IssueLabels // or other items as they are added
}

func generateRepoCommit(e Engine, repo, templateRepo, generateRepo *Repository, tmpDir string) error {
commitTimeStr := time.Now().Format(time.RFC3339)
authorSig := repo.Owner.NewGitSig()

// Because this may call hooks we should pass in the environment
env := append(os.Environ(),
"GIT_AUTHOR_NAME="+authorSig.Name,
"GIT_AUTHOR_EMAIL="+authorSig.Email,
"GIT_AUTHOR_DATE="+commitTimeStr,
"GIT_COMMITTER_NAME="+authorSig.Name,
"GIT_COMMITTER_EMAIL="+authorSig.Email,
"GIT_COMMITTER_DATE="+commitTimeStr,
)

// Clone to temporary path and do the init commit.
templateRepoPath := templateRepo.repoPath(e)
_, stderr, err := process.GetManager().ExecDirEnv(
jolheiser marked this conversation as resolved.
Show resolved Hide resolved
10*time.Minute, "",
fmt.Sprintf("generateRepoCommit(git clone): %s", templateRepoPath),
env,
git.GitExecutable, "clone", "--depth", "1", templateRepoPath, tmpDir,
)
if err != nil {
return fmt.Errorf("git clone: %v - %s", err, stderr)
}

if err := os.RemoveAll(path.Join(tmpDir, ".git")); err != nil {
return fmt.Errorf("remove git dir: %v", err)
}

// Variable expansion in _template files
if err := filepath.Walk(tmpDir, func(path string, info os.FileInfo, walkErr error) error {
if walkErr != nil {
return walkErr
}

if info.IsDir() {
return nil
}

ext := filepath.Ext(path)
pathNoExt := strings.TrimSuffix(path, ext)

if !strings.HasSuffix(pathNoExt, "_template") {
return nil
}

newPath := fmt.Sprintf("%s%s", strings.TrimSuffix(pathNoExt, "_template"), ext)
jolheiser marked this conversation as resolved.
Show resolved Hide resolved

content, err := ioutil.ReadFile(path)
if err != nil {
return err
}

if err := ioutil.WriteFile(newPath,
[]byte(generateExpansion(string(content), templateRepo, generateRepo)),
0644); err != nil {
return err
}

return os.Remove(path)
}); err != nil {
return err
}

if err := git.InitRepository(tmpDir, false); err != nil {
return err
}

repoPath := repo.repoPath(e)
_, stderr, err = process.GetManager().ExecDirEnv(
-1, tmpDir,
fmt.Sprintf("generateRepoCommit(git remote add): %s", repoPath),
env,
git.GitExecutable, "remote", "add", "origin", repoPath,
)
if err != nil {
return fmt.Errorf("git remote add: %v - %s", err, stderr)
}

return initRepoCommit(tmpDir, repo.Owner)
}

// generateRepository initializes repository from template
func generateRepository(e Engine, repo, templateRepo *Repository) (err error) {
func generateRepository(e Engine, repo, templateRepo, generateRepo *Repository) (err error) {
tmpDir := filepath.Join(os.TempDir(), "gitea-"+repo.Name+"-"+com.ToStr(time.Now().Nanosecond()))

if err := os.MkdirAll(tmpDir, os.ModePerm); err != nil {
Expand All @@ -50,7 +136,7 @@ func generateRepository(e Engine, repo, templateRepo *Repository) (err error) {
}
}()

if err = generateRepoCommit(e, repo, templateRepo, tmpDir); err != nil {
if err = generateRepoCommit(e, repo, templateRepo, generateRepo, tmpDir); err != nil {
return fmt.Errorf("generateRepoCommit: %v", err)
}

Expand Down Expand Up @@ -95,7 +181,7 @@ func GenerateRepository(ctx DBContext, doer, owner *User, templateRepo *Reposito

// GenerateGitContent generates git content from a template repository
func GenerateGitContent(ctx DBContext, templateRepo, generateRepo *Repository) error {
if err := generateRepository(ctx.e, generateRepo, templateRepo); err != nil {
if err := generateRepository(ctx.e, generateRepo, templateRepo, generateRepo); err != nil {
return err
}

Expand Down Expand Up @@ -144,7 +230,7 @@ func GenerateGitHooks(ctx DBContext, templateRepo, generateRepo *Repository) err
return err
}

generateHook.Content = templateHook.Content
generateHook.Content = generateExpansion(templateHook.Content, templateRepo, generateRepo)
jolheiser marked this conversation as resolved.
Show resolved Hide resolved
if err := generateHook.Update(); err != nil {
return err
}
Expand Down Expand Up @@ -210,3 +296,32 @@ func GenerateIssueLabels(ctx DBContext, templateRepo, generateRepo *Repository)
}
return nil
}

func generateExpansion(src string, templateRepo, generateRepo *Repository) string {
return os.Expand(src, func(key string) string {
jolheiser marked this conversation as resolved.
Show resolved Hide resolved
switch key {
case "REPO_NAME":
jolheiser marked this conversation as resolved.
Show resolved Hide resolved
return generateRepo.Name
case "TEMPLATE_NAME":
return templateRepo.Name
case "REPO_OWNER":
return generateRepo.MustOwnerName()
case "TEMPLATE_OWNER":
return templateRepo.MustOwnerName()
case "REPO_LINK":
return generateRepo.Link()
case "TEMPLATE_LINK":
return templateRepo.Link()
case "REPO_HTTPS_URL":
return generateRepo.CloneLink().HTTPS
case "TEMPLATE_HTTPS_URL":
return templateRepo.CloneLink().HTTPS
case "REPO_SSH_URL":
return generateRepo.CloneLink().SSH
case "TEMPLATE_SSH_URL":
return templateRepo.CloneLink().SSH
default:
return key
jolheiser marked this conversation as resolved.
Show resolved Hide resolved
}
})
}