Skip to content

Commit

Permalink
More expansions in template repositories (#10021)
Browse files Browse the repository at this point in the history
* Super expansion
* Explain which features are in 1.11 vs 1.12
* Move imports

Signed-off-by: jolheiser <[email protected]>
  • Loading branch information
jolheiser authored and zeripath committed Jan 28, 2020
1 parent 206a031 commit 28216bd
Show file tree
Hide file tree
Showing 18 changed files with 1,814 additions and 80 deletions.
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
---
date: "2019-11-28:00:00+02:00"
title: "The .gitea Directory"
slug: "gitea-directory"
weight: 40
title: "Template Repositories"
slug: "template-repositories"
weight: 14
toc: true
draft: false
menu:
sidebar:
parent: "features"
name: "The .gitea Directory"
weight: 50
identifier: "gitea-directory"
parent: "usage"
name: "Template Repositories"
weight: 14
identifier: "template-repositories"
---

# The .gitea directory
Gitea repositories can include a `.gitea` directory at their base which will store settings/configurations for certain features.

## Templates
Gitea includes template repositories, and one feature implemented with them is auto-expansion of specific variables within your template files.
## Template Repositories
Gitea `1.11.0` and above includes template repositories, and one feature implemented with them is auto-expansion of specific variables within your template files.
To tell Gitea which files to expand, you must include a `template` file inside the `.gitea` directory of the template repository.
Gitea uses [gobwas/glob](https://github.com/gobwas/glob) for its glob syntax. It closely resembles a traditional `.gitignore`, however there may be slight differences.

Expand All @@ -42,15 +39,34 @@ a/b/c/d.json
In any file matched by the above globs, certain variables will be expanded.
All variables must be of the form `$VAR` or `${VAR}`. To escape an expansion, use a double `$$`, such as `$$VAR` or `$${VAR}`

| Variable | Expands To |
|----------------------|-----------------------------------------------------|
| REPO_NAME | The name of the generated repository |
| TEMPLATE_NAME | The name of the template repository |
| REPO_DESCRIPTION | The description of the generated repository |
| TEMPLATE_DESCRIPTION | The description of the template repository |
| REPO_LINK | The URL to the generated repository |
| TEMPLATE_LINK | The URL to the template repository |
| REPO_HTTPS_URL | The HTTP(S) clone link for the generated repository |
| TEMPLATE_HTTPS_URL | The HTTP(S) clone link for the template repository |
| REPO_SSH_URL | The SSH clone link for the generated repository |
| TEMPLATE_SSH_URL | The SSH clone link for the template repository |
| Variable | Expands To | Transformable |
|----------------------|-----------------------------------------------------|---------------|
| REPO_NAME | The name of the generated repository ||
| TEMPLATE_NAME | The name of the template repository ||
| REPO_DESCRIPTION | The description of the generated repository ||
| TEMPLATE_DESCRIPTION | The description of the template repository ||
| REPO_OWNER | The owner of the generated repository ||
| TEMPLATE_OWNER | The owner of the template repository ||
| REPO_LINK | The URL to the generated repository ||
| TEMPLATE_LINK | The URL to the template repository ||
| REPO_HTTPS_URL | The HTTP(S) clone link for the generated repository ||
| TEMPLATE_HTTPS_URL | The HTTP(S) clone link for the template repository ||
| REPO_SSH_URL | The SSH clone link for the generated repository ||
| TEMPLATE_SSH_URL | The SSH clone link for the template repository ||

### Transformers :robot:
Gitea `1.12.0` adds a few transformers to some of the applicable variables above.
For example, to get `REPO_NAME` in `PASCAL`-case, your template would use `${REPO_NAME_PASCAL}`

Feeding `go-sdk` to the available transformers yields...

| Transformer | Effect |
|-------------|------------|
| SNAKE | go_sdk |
| KEBAB | go-sdk |
| CAMEL | goSdk |
| PASCAL | GoSdk |
| LOWER | go-sdk |
| UPPER | GO-SDK |
| TITLE | Go-Sdk |

1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ require (
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
github.com/google/go-github/v24 v24.0.1
github.com/gorilla/context v1.1.1
github.com/huandu/xstrings v1.3.0
github.com/issue9/assert v1.3.2 // indirect
github.com/issue9/identicon v0.0.0-20160320065130-d36b54562f4c
github.com/jaytaylor/html2text v0.0.0-20160923191438-8fb95d837f7d
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huandu/xstrings v1.3.0 h1:gvV6jG9dTgFEncxo+AF7PH6MZXi/vZl25owA/8Dg8Wo=
github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/issue9/assert v1.3.2 h1:IaTa37u4m1fUuTH9K9ldO5IONKVDXjLiUO1T9vj0OF0=
github.com/issue9/assert v1.3.2/go.mod h1:9Ger+iz8X7r1zMYYwEhh++2wMGWcNN2oVI+zIQXxcio=
Expand Down
138 changes: 82 additions & 56 deletions modules/repository/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,38 +16,62 @@ import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"

"github.com/huandu/xstrings"
)

type transformer struct {
Name string
Transform func(string) string
}

type expansion struct {
Name string
Value string
Transformers []transformer
}

var defaultTransformers = []transformer{
{Name: "SNAKE", Transform: xstrings.ToSnakeCase},
{Name: "KEBAB", Transform: xstrings.ToKebabCase},
{Name: "CAMEL", Transform: func(str string) string {
return xstrings.FirstRuneToLower(xstrings.ToCamelCase(str))
}},
{Name: "PASCAL", Transform: xstrings.ToCamelCase},
{Name: "LOWER", Transform: strings.ToLower},
{Name: "UPPER", Transform: strings.ToUpper},
{Name: "TITLE", Transform: strings.Title},
}

func generateExpansion(src string, templateRepo, generateRepo *models.Repository) string {
expansions := []expansion{
{Name: "REPO_NAME", Value: generateRepo.Name, Transformers: defaultTransformers},
{Name: "TEMPLATE_NAME", Value: templateRepo.Name, Transformers: defaultTransformers},
{Name: "REPO_DESCRIPTION", Value: generateRepo.Description, Transformers: nil},
{Name: "TEMPLATE_DESCRIPTION", Value: templateRepo.Description, Transformers: nil},
{Name: "REPO_OWNER", Value: generateRepo.OwnerName, Transformers: defaultTransformers},
{Name: "TEMPLATE_OWNER", Value: templateRepo.OwnerName, Transformers: defaultTransformers},
{Name: "REPO_LINK", Value: generateRepo.Link(), Transformers: nil},
{Name: "TEMPLATE_LINK", Value: templateRepo.Link(), Transformers: nil},
{Name: "REPO_HTTPS_URL", Value: generateRepo.CloneLink().HTTPS, Transformers: nil},
{Name: "TEMPLATE_HTTPS_URL", Value: templateRepo.CloneLink().HTTPS, Transformers: nil},
{Name: "REPO_SSH_URL", Value: generateRepo.CloneLink().SSH, Transformers: nil},
{Name: "TEMPLATE_SSH_URL", Value: templateRepo.CloneLink().SSH, Transformers: nil},
}

var expansionMap = make(map[string]string)
for _, e := range expansions {
expansionMap[e.Name] = e.Value
for _, tr := range e.Transformers {
expansionMap[fmt.Sprintf("%s_%s", e.Name, tr.Name)] = tr.Transform(e.Value)
}
}

return os.Expand(src, func(key string) string {
switch key {
case "REPO_NAME":
return generateRepo.Name
case "TEMPLATE_NAME":
return templateRepo.Name
case "REPO_DESCRIPTION":
return generateRepo.Description
case "TEMPLATE_DESCRIPTION":
return templateRepo.Description
case "REPO_OWNER":
return generateRepo.OwnerName
case "TEMPLATE_OWNER":
return templateRepo.OwnerName
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
if expansion, ok := expansionMap[key]; ok {
return expansion
}
return key
})
}

Expand Down Expand Up @@ -104,41 +128,43 @@ func generateRepoCommit(repo, templateRepo, generateRepo *models.Repository, tmp
return fmt.Errorf("checkGiteaTemplate: %v", err)
}

if err := os.Remove(gt.Path); err != nil {
return fmt.Errorf("remove .giteatemplate: %v", err)
}

// Avoid walking tree if there are no globs
if len(gt.Globs()) > 0 {
tmpDirSlash := strings.TrimSuffix(filepath.ToSlash(tmpDir), "/") + "/"
if err := filepath.Walk(tmpDirSlash, func(path string, info os.FileInfo, walkErr error) error {
if walkErr != nil {
return walkErr
}
if gt != nil {
if err := os.Remove(gt.Path); err != nil {
return fmt.Errorf("remove .giteatemplate: %v", err)
}

if info.IsDir() {
return nil
}
// Avoid walking tree if there are no globs
if len(gt.Globs()) > 0 {
tmpDirSlash := strings.TrimSuffix(filepath.ToSlash(tmpDir), "/") + "/"
if err := filepath.Walk(tmpDirSlash, func(path string, info os.FileInfo, walkErr error) error {
if walkErr != nil {
return walkErr
}

base := strings.TrimPrefix(filepath.ToSlash(path), tmpDirSlash)
for _, g := range gt.Globs() {
if g.Match(base) {
content, err := ioutil.ReadFile(path)
if err != nil {
return err
}
if info.IsDir() {
return nil
}

if err := ioutil.WriteFile(path,
[]byte(generateExpansion(string(content), templateRepo, generateRepo)),
0644); err != nil {
return err
base := strings.TrimPrefix(filepath.ToSlash(path), tmpDirSlash)
for _, g := range gt.Globs() {
if g.Match(base) {
content, err := ioutil.ReadFile(path)
if err != nil {
return err
}

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

Expand Down
24 changes: 24 additions & 0 deletions vendor/github.com/huandu/xstrings/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions vendor/github.com/huandu/xstrings/.travis.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions vendor/github.com/huandu/xstrings/CONTRIBUTING.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions vendor/github.com/huandu/xstrings/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 28216bd

Please sign in to comment.