Skip to content

Commit 28216bd

Browse files
jolheiserzeripath
authored andcommitted
More expansions in template repositories (#10021)
* Super expansion * Explain which features are in 1.11 vs 1.12 * Move imports Signed-off-by: jolheiser <[email protected]>
1 parent 206a031 commit 28216bd

File tree

18 files changed

+1814
-80
lines changed

18 files changed

+1814
-80
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
11
---
22
date: "2019-11-28:00:00+02:00"
3-
title: "The .gitea Directory"
4-
slug: "gitea-directory"
5-
weight: 40
3+
title: "Template Repositories"
4+
slug: "template-repositories"
5+
weight: 14
66
toc: true
77
draft: false
88
menu:
99
sidebar:
10-
parent: "features"
11-
name: "The .gitea Directory"
12-
weight: 50
13-
identifier: "gitea-directory"
10+
parent: "usage"
11+
name: "Template Repositories"
12+
weight: 14
13+
identifier: "template-repositories"
1414
---
1515

16-
# The .gitea directory
17-
Gitea repositories can include a `.gitea` directory at their base which will store settings/configurations for certain features.
18-
19-
## Templates
20-
Gitea includes template repositories, and one feature implemented with them is auto-expansion of specific variables within your template files.
16+
## Template Repositories
17+
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.
2118
To tell Gitea which files to expand, you must include a `template` file inside the `.gitea` directory of the template repository.
2219
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.
2320

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

45-
| Variable | Expands To |
46-
|----------------------|-----------------------------------------------------|
47-
| REPO_NAME | The name of the generated repository |
48-
| TEMPLATE_NAME | The name of the template repository |
49-
| REPO_DESCRIPTION | The description of the generated repository |
50-
| TEMPLATE_DESCRIPTION | The description of the template repository |
51-
| REPO_LINK | The URL to the generated repository |
52-
| TEMPLATE_LINK | The URL to the template repository |
53-
| REPO_HTTPS_URL | The HTTP(S) clone link for the generated repository |
54-
| TEMPLATE_HTTPS_URL | The HTTP(S) clone link for the template repository |
55-
| REPO_SSH_URL | The SSH clone link for the generated repository |
56-
| TEMPLATE_SSH_URL | The SSH clone link for the template repository |
42+
| Variable | Expands To | Transformable |
43+
|----------------------|-----------------------------------------------------|---------------|
44+
| REPO_NAME | The name of the generated repository ||
45+
| TEMPLATE_NAME | The name of the template repository ||
46+
| REPO_DESCRIPTION | The description of the generated repository ||
47+
| TEMPLATE_DESCRIPTION | The description of the template repository ||
48+
| REPO_OWNER | The owner of the generated repository ||
49+
| TEMPLATE_OWNER | The owner of the template repository ||
50+
| REPO_LINK | The URL to the generated repository ||
51+
| TEMPLATE_LINK | The URL to the template repository ||
52+
| REPO_HTTPS_URL | The HTTP(S) clone link for the generated repository ||
53+
| TEMPLATE_HTTPS_URL | The HTTP(S) clone link for the template repository ||
54+
| REPO_SSH_URL | The SSH clone link for the generated repository ||
55+
| TEMPLATE_SSH_URL | The SSH clone link for the template repository ||
56+
57+
### Transformers :robot:
58+
Gitea `1.12.0` adds a few transformers to some of the applicable variables above.
59+
For example, to get `REPO_NAME` in `PASCAL`-case, your template would use `${REPO_NAME_PASCAL}`
60+
61+
Feeding `go-sdk` to the available transformers yields...
62+
63+
| Transformer | Effect |
64+
|-------------|------------|
65+
| SNAKE | go_sdk |
66+
| KEBAB | go-sdk |
67+
| CAMEL | goSdk |
68+
| PASCAL | GoSdk |
69+
| LOWER | go-sdk |
70+
| UPPER | GO-SDK |
71+
| TITLE | Go-Sdk |
72+

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ require (
5050
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
5151
github.com/google/go-github/v24 v24.0.1
5252
github.com/gorilla/context v1.1.1
53+
github.com/huandu/xstrings v1.3.0
5354
github.com/issue9/assert v1.3.2 // indirect
5455
github.com/issue9/identicon v0.0.0-20160320065130-d36b54562f4c
5556
github.com/jaytaylor/html2text v0.0.0-20160923191438-8fb95d837f7d

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,8 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
306306
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
307307
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
308308
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
309+
github.com/huandu/xstrings v1.3.0 h1:gvV6jG9dTgFEncxo+AF7PH6MZXi/vZl25owA/8Dg8Wo=
310+
github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
309311
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
310312
github.com/issue9/assert v1.3.2 h1:IaTa37u4m1fUuTH9K9ldO5IONKVDXjLiUO1T9vj0OF0=
311313
github.com/issue9/assert v1.3.2/go.mod h1:9Ger+iz8X7r1zMYYwEhh++2wMGWcNN2oVI+zIQXxcio=

modules/repository/generate.go

+82-56
Original file line numberDiff line numberDiff line change
@@ -16,38 +16,62 @@ import (
1616
"code.gitea.io/gitea/models"
1717
"code.gitea.io/gitea/modules/git"
1818
"code.gitea.io/gitea/modules/log"
19+
20+
"github.com/huandu/xstrings"
1921
)
2022

23+
type transformer struct {
24+
Name string
25+
Transform func(string) string
26+
}
27+
28+
type expansion struct {
29+
Name string
30+
Value string
31+
Transformers []transformer
32+
}
33+
34+
var defaultTransformers = []transformer{
35+
{Name: "SNAKE", Transform: xstrings.ToSnakeCase},
36+
{Name: "KEBAB", Transform: xstrings.ToKebabCase},
37+
{Name: "CAMEL", Transform: func(str string) string {
38+
return xstrings.FirstRuneToLower(xstrings.ToCamelCase(str))
39+
}},
40+
{Name: "PASCAL", Transform: xstrings.ToCamelCase},
41+
{Name: "LOWER", Transform: strings.ToLower},
42+
{Name: "UPPER", Transform: strings.ToUpper},
43+
{Name: "TITLE", Transform: strings.Title},
44+
}
45+
2146
func generateExpansion(src string, templateRepo, generateRepo *models.Repository) string {
47+
expansions := []expansion{
48+
{Name: "REPO_NAME", Value: generateRepo.Name, Transformers: defaultTransformers},
49+
{Name: "TEMPLATE_NAME", Value: templateRepo.Name, Transformers: defaultTransformers},
50+
{Name: "REPO_DESCRIPTION", Value: generateRepo.Description, Transformers: nil},
51+
{Name: "TEMPLATE_DESCRIPTION", Value: templateRepo.Description, Transformers: nil},
52+
{Name: "REPO_OWNER", Value: generateRepo.OwnerName, Transformers: defaultTransformers},
53+
{Name: "TEMPLATE_OWNER", Value: templateRepo.OwnerName, Transformers: defaultTransformers},
54+
{Name: "REPO_LINK", Value: generateRepo.Link(), Transformers: nil},
55+
{Name: "TEMPLATE_LINK", Value: templateRepo.Link(), Transformers: nil},
56+
{Name: "REPO_HTTPS_URL", Value: generateRepo.CloneLink().HTTPS, Transformers: nil},
57+
{Name: "TEMPLATE_HTTPS_URL", Value: templateRepo.CloneLink().HTTPS, Transformers: nil},
58+
{Name: "REPO_SSH_URL", Value: generateRepo.CloneLink().SSH, Transformers: nil},
59+
{Name: "TEMPLATE_SSH_URL", Value: templateRepo.CloneLink().SSH, Transformers: nil},
60+
}
61+
62+
var expansionMap = make(map[string]string)
63+
for _, e := range expansions {
64+
expansionMap[e.Name] = e.Value
65+
for _, tr := range e.Transformers {
66+
expansionMap[fmt.Sprintf("%s_%s", e.Name, tr.Name)] = tr.Transform(e.Value)
67+
}
68+
}
69+
2270
return os.Expand(src, func(key string) string {
23-
switch key {
24-
case "REPO_NAME":
25-
return generateRepo.Name
26-
case "TEMPLATE_NAME":
27-
return templateRepo.Name
28-
case "REPO_DESCRIPTION":
29-
return generateRepo.Description
30-
case "TEMPLATE_DESCRIPTION":
31-
return templateRepo.Description
32-
case "REPO_OWNER":
33-
return generateRepo.OwnerName
34-
case "TEMPLATE_OWNER":
35-
return templateRepo.OwnerName
36-
case "REPO_LINK":
37-
return generateRepo.Link()
38-
case "TEMPLATE_LINK":
39-
return templateRepo.Link()
40-
case "REPO_HTTPS_URL":
41-
return generateRepo.CloneLink().HTTPS
42-
case "TEMPLATE_HTTPS_URL":
43-
return templateRepo.CloneLink().HTTPS
44-
case "REPO_SSH_URL":
45-
return generateRepo.CloneLink().SSH
46-
case "TEMPLATE_SSH_URL":
47-
return templateRepo.CloneLink().SSH
48-
default:
49-
return key
71+
if expansion, ok := expansionMap[key]; ok {
72+
return expansion
5073
}
74+
return key
5175
})
5276
}
5377

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

107-
if err := os.Remove(gt.Path); err != nil {
108-
return fmt.Errorf("remove .giteatemplate: %v", err)
109-
}
110-
111-
// Avoid walking tree if there are no globs
112-
if len(gt.Globs()) > 0 {
113-
tmpDirSlash := strings.TrimSuffix(filepath.ToSlash(tmpDir), "/") + "/"
114-
if err := filepath.Walk(tmpDirSlash, func(path string, info os.FileInfo, walkErr error) error {
115-
if walkErr != nil {
116-
return walkErr
117-
}
131+
if gt != nil {
132+
if err := os.Remove(gt.Path); err != nil {
133+
return fmt.Errorf("remove .giteatemplate: %v", err)
134+
}
118135

119-
if info.IsDir() {
120-
return nil
121-
}
136+
// Avoid walking tree if there are no globs
137+
if len(gt.Globs()) > 0 {
138+
tmpDirSlash := strings.TrimSuffix(filepath.ToSlash(tmpDir), "/") + "/"
139+
if err := filepath.Walk(tmpDirSlash, func(path string, info os.FileInfo, walkErr error) error {
140+
if walkErr != nil {
141+
return walkErr
142+
}
122143

123-
base := strings.TrimPrefix(filepath.ToSlash(path), tmpDirSlash)
124-
for _, g := range gt.Globs() {
125-
if g.Match(base) {
126-
content, err := ioutil.ReadFile(path)
127-
if err != nil {
128-
return err
129-
}
144+
if info.IsDir() {
145+
return nil
146+
}
130147

131-
if err := ioutil.WriteFile(path,
132-
[]byte(generateExpansion(string(content), templateRepo, generateRepo)),
133-
0644); err != nil {
134-
return err
148+
base := strings.TrimPrefix(filepath.ToSlash(path), tmpDirSlash)
149+
for _, g := range gt.Globs() {
150+
if g.Match(base) {
151+
content, err := ioutil.ReadFile(path)
152+
if err != nil {
153+
return err
154+
}
155+
156+
if err := ioutil.WriteFile(path,
157+
[]byte(generateExpansion(string(content), templateRepo, generateRepo)),
158+
0644); err != nil {
159+
return err
160+
}
161+
break
135162
}
136-
break
137163
}
164+
return nil
165+
}); err != nil {
166+
return err
138167
}
139-
return nil
140-
}); err != nil {
141-
return err
142168
}
143169
}
144170

vendor/github.com/huandu/xstrings/.gitignore

+24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/huandu/xstrings/.travis.yml

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/huandu/xstrings/CONTRIBUTING.md

+23
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/huandu/xstrings/LICENSE

+22
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)