Sfoglia il codice sorgente

wiki: finish new

tags/v0.9.99
Unknwon 8 anni fa
parent
commit
392f3ee210

+ 1
- 0
cmd/web.go Vedi File



m.Group("/wiki", func() { m.Group("/wiki", func() {
m.Get("/?:page", repo.Wiki) m.Get("/?:page", repo.Wiki)
m.Get("/_list", repo.WikiList)


m.Group("", func() { m.Group("", func() {
m.Combo("/_new").Get(repo.NewWiki). m.Combo("/_new").Get(repo.NewWiki).

+ 1
- 0
conf/locale/locale_en-US.ini Vedi File

wiki.new_page = Create New Page wiki.new_page = Create New Page
wiki.default_commit_message = Write a note about this update (optional). wiki.default_commit_message = Write a note about this update (optional).
wiki.save_page = Save Page wiki.save_page = Save Page
wiki.last_commit_info = %s edited this page %s


settings = Settings settings = Settings
settings.options = Options settings.options = Options

+ 0
- 1956
config.codekit
File diff soppresso perché troppo grande
Vedi File


+ 4
- 0
models/release.go Vedi File

return x.Get(&Release{RepoID: repoID, LowerTagName: strings.ToLower(tagName)}) return x.Get(&Release{RepoID: repoID, LowerTagName: strings.ToLower(tagName)})
} }


func init() {
git.GetVersion()
}

func createTag(gitRepo *git.Repository, rel *Release) error { func createTag(gitRepo *git.Repository, rel *Release) error {
// Only actual create when publish. // Only actual create when publish.
if !rel.IsDraft { if !rel.IsDraft {

+ 32
- 37
models/repo.go Vedi File



"github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/bindata" "github.com/gogits/gogs/modules/bindata"
oldgit "github.com/gogits/gogs/modules/git"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/process" "github.com/gogits/gogs/modules/process"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
return path.Join(setting.AppDataPath, "tmp/local", com.ToStr(repo.ID)) return path.Join(setting.AppDataPath, "tmp/local", com.ToStr(repo.ID))
} }


// UpdateLocalCopy makes sure the local copy of repository is up-to-date.
func (repo *Repository) UpdateLocalCopy() error {
repoPath := repo.RepoPath()
localPath := repo.LocalCopyPath()
func updateLocalCopy(repoPath, localPath string) error {
if !com.IsExist(localPath) { if !com.IsExist(localPath) {
_, stderr, err := process.Exec(
fmt.Sprintf("UpdateLocalCopy(git clone): %s", repoPath), "git", "clone", repoPath, localPath)
if err != nil {
return fmt.Errorf("git clone: %v - %s", err, stderr)
if err := git.Clone(repoPath, localPath); err != nil {
return fmt.Errorf("Clone: %v", err)
} }
} else { } else {
_, stderr, err := process.ExecDir(-1, localPath,
fmt.Sprintf("UpdateLocalCopy(git pull --all): %s", repoPath), "git", "pull", "--all")
if err != nil {
return fmt.Errorf("git pull: %v - %s", err, stderr)
if err := git.Pull(localPath, true); err != nil {
return fmt.Errorf("Pull: %v", err)
} }
} }

return nil return nil
} }


// UpdateLocalCopy makes sure the local copy of repository is up-to-date.
func (repo *Repository) UpdateLocalCopy() error {
return updateLocalCopy(repo.RepoPath(), repo.LocalCopyPath())
}

// PatchPath returns corresponding patch file path of repository by given issue ID. // PatchPath returns corresponding patch file path of repository by given issue ID.
func (repo *Repository) PatchPath(index int64) (string, error) { func (repo *Repository) PatchPath(index int64) (string, error) {
if err := repo.GetOwner(); err != nil { if err := repo.GetOwner(); err != nil {
return updateMirror(x, m) return updateMirror(x, m)
} }


func createUpdateHook(repoPath string) error {
return git.SetUpdateHook(repoPath,
fmt.Sprintf(_TPL_UPDATE_HOOK, setting.ScriptType, "\""+setting.AppPath+"\"", setting.CustomConf))
}

// MirrorRepository creates a mirror repository from source. // MirrorRepository creates a mirror repository from source.
func MirrorRepository(repoId int64, userName, repoName, repoPath, url string) error { func MirrorRepository(repoId int64, userName, repoName, repoPath, url string) error {
_, stderr, err := process.ExecTimeout(10*time.Minute, _, stderr, err := process.ExecTimeout(10*time.Minute,
} }
} }


// Check if repository has master branch, if so set it to default branch.
gitRepo, err := oldgit.OpenRepository(repoPath)
// Try to get HEAD branch and set it as default branch.
gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
log.Error(4, "OpenRepository: %v", err)
return repo, nil
}
headBranch, err := gitRepo.GetHEADBranch()
if err != nil { if err != nil {
return repo, fmt.Errorf("open git repository: %v", err)
log.Error(4, "GetHEADBranch: %v", err)
return repo, nil
} }
if gitRepo.IsBranchExist("master") {
repo.DefaultBranch = "master"
if headBranch != nil {
repo.DefaultBranch = headBranch.Name
} }


return repo, UpdateRepository(repo, false) return repo, UpdateRepository(repo, false)
} }


// initRepoCommit temporarily changes with work directory. // initRepoCommit temporarily changes with work directory.
func initRepoCommit(tmpPath string, sig *oldgit.Signature) (err error) {
func initRepoCommit(tmpPath string, sig *git.Signature) (err error) {
var stderr string var stderr string
if _, stderr, err = process.ExecDir(-1, if _, stderr, err = process.ExecDir(-1,
tmpPath, fmt.Sprintf("initRepoCommit (git add): %s", tmpPath), tmpPath, fmt.Sprintf("initRepoCommit (git add): %s", tmpPath),
return nil return nil
} }


func createUpdateHook(repoPath string) error {
hookPath := path.Join(repoPath, "hooks/update")
os.MkdirAll(path.Dir(hookPath), os.ModePerm)
return ioutil.WriteFile(hookPath,
[]byte(fmt.Sprintf(_TPL_UPDATE_HOOK, setting.ScriptType, "\""+setting.AppPath+"\"", setting.CustomConf)), 0777)
}

type CreateRepoOptions struct { type CreateRepoOptions struct {
Name string Name string
Description string Description string
} }


// InitRepository initializes README and .gitignore if needed. // InitRepository initializes README and .gitignore if needed.
func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts CreateRepoOptions) error {
func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts CreateRepoOptions) (err error) {
// Somehow the directory could exist. // Somehow the directory could exist.
if com.IsExist(repoPath) { if com.IsExist(repoPath) {
return fmt.Errorf("initRepository: path already exists: %s", repoPath) return fmt.Errorf("initRepository: path already exists: %s", repoPath)
} }


// Init bare new repository. // Init bare new repository.
os.MkdirAll(repoPath, os.ModePerm)
_, stderr, err := process.ExecDir(-1, repoPath,
fmt.Sprintf("initRepository (git init --bare): %s", repoPath), "git", "init", "--bare")
if err != nil {
return fmt.Errorf("git init --bare: %v - %s", err, stderr)
}

if err := createUpdateHook(repoPath); err != nil {
return err
if err = git.InitRepository(repoPath, true); err != nil {
return fmt.Errorf("InitRepository: %v", err)
} else if err = createUpdateHook(repoPath); err != nil {
return fmt.Errorf("createUpdateHook: %v", err)
} }


tmpDir := filepath.Join(os.TempDir(), "gogs-"+repo.Name+"-"+com.ToStr(time.Now().Nanosecond())) tmpDir := filepath.Join(os.TempDir(), "gogs-"+repo.Name+"-"+com.ToStr(time.Now().Nanosecond()))

+ 6
- 4
models/user.go Vedi File

"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
"github.com/nfnt/resize" "github.com/nfnt/resize"


"github.com/gogits/git-shell"

"github.com/gogits/gogs/modules/avatar" "github.com/gogits/gogs/modules/avatar"
"github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/git"
oldgit "github.com/gogits/gogs/modules/git"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
) )
// UserCommit represents a commit with validation of user. // UserCommit represents a commit with validation of user.
type UserCommit struct { type UserCommit struct {
User *User User *User
*git.Commit
*oldgit.Commit
} }


// ValidateCommitWithEmail chceck if author's e-mail of commit is corresponsind to a user. // ValidateCommitWithEmail chceck if author's e-mail of commit is corresponsind to a user.
func ValidateCommitWithEmail(c *git.Commit) *User {
func ValidateCommitWithEmail(c *oldgit.Commit) *User {
u, err := GetUserByEmail(c.Author.Email) u, err := GetUserByEmail(c.Author.Email)
if err != nil { if err != nil {
return nil return nil
e = oldCommits.Front() e = oldCommits.Front()
) )
for e != nil { for e != nil {
c := e.Value.(*git.Commit)
c := e.Value.(*oldgit.Commit)


if v, ok := emails[c.Author.Email]; !ok { if v, ok := emails[c.Author.Email]; !ok {
u, _ = GetUserByEmail(c.Author.Email) u, _ = GetUserByEmail(c.Author.Email)

+ 101
- 3
models/wiki.go Vedi File



import ( import (
"fmt" "fmt"
"io/ioutil"
"path"
"path/filepath" "path/filepath"
"strings" "strings"
"sync"


"github.com/Unknwon/com" "github.com/Unknwon/com"


"github.com/gogits/git-shell" "github.com/gogits/git-shell"

"github.com/gogits/gogs/modules/setting"
) )


// ToWikiPageName formats a string to corresponding wiki URL name.
func ToWikiPageName(name string) string {
// workingPool represents a pool of working status which makes sure
// that only one instance of same task is performing at a time.
// However, different type of tasks can performing at the same time.
type workingPool struct {
lock sync.Mutex
pool map[string]*sync.Mutex
count map[string]int
}

// CheckIn checks in a task and waits if others are running.
func (p *workingPool) CheckIn(name string) {
p.lock.Lock()

lock, has := p.pool[name]
if !has {
lock = &sync.Mutex{}
p.pool[name] = lock
}
p.count[name]++

p.lock.Unlock()
lock.Lock()
}

// CheckOut checks out a task to let other tasks run.
func (p *workingPool) CheckOut(name string) {
p.lock.Lock()
defer p.lock.Unlock()

p.pool[name].Unlock()
if p.count[name] == 1 {
delete(p.pool, name)
delete(p.count, name)
} else {
p.count[name]--
}
}

var wikiWorkingPool = &workingPool{
pool: make(map[string]*sync.Mutex),
count: make(map[string]int),
}

// ToWikiPageURL formats a string to corresponding wiki URL name.
func ToWikiPageURL(name string) string {
return strings.Replace(name, " ", "-", -1) return strings.Replace(name, " ", "-", -1)
} }


// ToWikiPageName formats a URL back to corresponding wiki page name.
func ToWikiPageName(name string) string {
return strings.Replace(name, "-", " ", -1)
}

// WikiPath returns wiki data path by given user and repository name. // WikiPath returns wiki data path by given user and repository name.
func WikiPath(userName, repoName string) string { func WikiPath(userName, repoName string) string {
return filepath.Join(UserPath(userName), strings.ToLower(repoName)+".wiki.git") return filepath.Join(UserPath(userName), strings.ToLower(repoName)+".wiki.git")
return nil return nil
} }


func (repo *Repository) LocalWikiPath() string {
return path.Join(setting.AppDataPath, "tmp/local-wiki", com.ToStr(repo.ID))
}

// UpdateLocalWiki makes sure the local copy of repository wiki is up-to-date.
func (repo *Repository) UpdateLocalWiki() error {
return updateLocalCopy(repo.WikiPath(), repo.LocalWikiPath())
}

// AddWikiPage adds new page to repository wiki. // AddWikiPage adds new page to repository wiki.
func (repo *Repository) AddWikiPage(title, content, message string) (err error) {
func (repo *Repository) AddWikiPage(doer *User, title, content, message string) (err error) {
wikiWorkingPool.CheckIn(com.ToStr(repo.ID))
defer wikiWorkingPool.CheckOut(com.ToStr(repo.ID))

if err = repo.InitWiki(); err != nil { if err = repo.InitWiki(); err != nil {
return fmt.Errorf("InitWiki: %v", err) return fmt.Errorf("InitWiki: %v", err)
} }


localPath := repo.LocalWikiPath()

// Discard local commits make sure even to remote when local copy exists.
if com.IsExist(localPath) {
// No need to check if nothing in the repository.
if git.IsBranchExist(localPath, "master") {
if err = git.Reset(localPath, true, "origin/master"); err != nil {
return fmt.Errorf("Reset: %v", err)
}
}
}

if err = repo.UpdateLocalWiki(); err != nil {
return fmt.Errorf("UpdateLocalWiki: %v", err)
}

title = strings.Replace(title, "/", " ", -1)
filename := path.Join(localPath, title+".md")
if err = ioutil.WriteFile(filename, []byte(content), 0666); err != nil {
return fmt.Errorf("WriteFile: %v", err)
}

if len(message) == 0 {
message = "Update page '" + title + "'"
}
if err = git.AddChanges(localPath, true); err != nil {
return fmt.Errorf("AddChanges: %v", err)
} else if err = git.CommitChanges(localPath, message, doer.NewGitSig()); err != nil {
return fmt.Errorf("CommitChanges: %v", err)
} else if err = git.Push(localPath, "origin", "master"); err != nil {
return fmt.Errorf("Push: %v", err)
}

return nil return nil
} }

+ 1
- 1
modules/auth/repo_form.go Vedi File



type NewWikiForm struct { type NewWikiForm struct {
Title string `binding:"Required"` Title string `binding:"Required"`
Content string
Content string `binding:"Required"`
Message string Message string
} }



+ 218
- 218
modules/bindata/bindata.go
File diff soppresso perché troppo grande
Vedi File


+ 1
- 13
public/config.codekit Vedi File

{ {
"CodeKitInfo": "This is a CodeKit 2.x project configuration file. It is designed to sync project settings across multiple machines. MODIFYING THE CONTENTS OF THIS FILE IS A POOR LIFE DECISION. If you do so, you will likely cause CodeKit to crash. This file is not useful unless accompanied by the project that created it in CodeKit 2. This file is not backwards-compatible with CodeKit 1.x. For more information, see: http:\/\/incident57.com\/codekit", "CodeKitInfo": "This is a CodeKit 2.x project configuration file. It is designed to sync project settings across multiple machines. MODIFYING THE CONTENTS OF THIS FILE IS A POOR LIFE DECISION. If you do so, you will likely cause CodeKit to crash. This file is not useful unless accompanied by the project that created it in CodeKit 2. This file is not backwards-compatible with CodeKit 1.x. For more information, see: http:\/\/incident57.com\/codekit",
"creatorBuild": "19102",
"creatorBuild": "19076",
"files": { "files": {
"\/css\/dropzone-4.2.0.css": { "\/css\/dropzone-4.2.0.css": {
"fileType": 16, "fileType": 16,
"active": 0, "active": 0,
"flagValue": -1 "flagValue": -1
}, },
"no_nested_string_interpolation": {
"active": 1,
"flagValue": -1
},
"no_plusplus": { "no_plusplus": {
"active": 0, "active": 0,
"flagValue": -1 "flagValue": -1
}, },
"no_private_function_fat_arrows": {
"active": 1,
"flagValue": -1
},
"no_stand_alone_at": { "no_stand_alone_at": {
"active": 1, "active": 1,
"flagValue": -1 "flagValue": -1
"active": 1, "active": 1,
"flagValue": -1 "flagValue": -1
}, },
"no_this": {
"active": 0,
"flagValue": -1
},
"no_throwing_strings": { "no_throwing_strings": {
"active": 1, "active": 1,
"flagValue": -1 "flagValue": -1

+ 14
- 0
public/css/gogs.css Vedi File

.repository.wiki.new .editor-preview { .repository.wiki.new .editor-preview {
background-color: white; background-color: white;
} }
.repository.wiki.view .ui.sub.header {
text-transform: none;
}
.repository.wiki.view .markdown {
padding: 15px 30px;
}
.repository.wiki.view .markdown h1:first-of-type,
.repository.wiki.view .markdown h2:first-of-type,
.repository.wiki.view .markdown h3:first-of-type,
.repository.wiki.view .markdown h4:first-of-type,
.repository.wiki.view .markdown h5:first-of-type,
.repository.wiki.view .markdown h6:first-of-type {
margin-top: 0;
}
.repository.settings.collaboration .collaborator.list { .repository.settings.collaboration .collaborator.list {
padding: 0; padding: 0;
} }

+ 18
- 0
public/less/_repository.less Vedi File

background-color: white; background-color: white;
} }
} }

&.view {
.header:not(.sub) {
// padding-left: 30px;
}
.ui.sub.header {
text-transform: none;
}
.markdown {
padding: 15px 30px;

h1, h2, h3, h4, h5, h6 {
&:first-of-type {
margin-top: 0;
}
}
}
}
} }


&.settings { &.settings {

+ 58
- 3
routers/repo/wiki.go Vedi File

package repo package repo


import ( import (
"io/ioutil"

"github.com/gogits/git-shell"

"github.com/gogits/gogs/models" "github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/auth" "github.com/gogits/gogs/modules/auth"
"github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/base"
) )


func Wiki(ctx *middleware.Context) { func Wiki(ctx *middleware.Context) {
ctx.Data["Title"] = ctx.Tr("repo.wiki")
ctx.Data["PageIsWiki"] = true ctx.Data["PageIsWiki"] = true


if !ctx.Repo.Repository.HasWiki() { if !ctx.Repo.Repository.HasWiki() {
ctx.Data["Title"] = ctx.Tr("repo.wiki")
ctx.HTML(200, WIKI_START) ctx.HTML(200, WIKI_START)
return return
} }


wikiRepo, err := git.OpenRepository(ctx.Repo.Repository.WikiPath())
if err != nil {
ctx.Handle(500, "OpenRepository", err)
return
}
commit, err := wikiRepo.GetCommitOfBranch("master")
if err != nil {
ctx.Handle(500, "GetCommitOfBranch", err)
return
}

page := models.ToWikiPageName(ctx.Params(":page"))
if len(page) == 0 {
page = "Home"
}
ctx.Data["Title"] = page
ctx.Data["RequireHighlightJS"] = true

blob, err := commit.GetBlobByPath(page + ".md")
if err != nil {
if git.IsErrNotExist(err) {
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_list")
} else {
ctx.Handle(500, "GetBlobByPath", err)
}
return
}
r, err := blob.Data()
if err != nil {
ctx.Handle(500, "Data", err)
return
}
data, err := ioutil.ReadAll(r)
if err != nil {
ctx.Handle(500, "ReadAll", err)
return
}
ctx.Data["Content"] = string(base.RenderMarkdown(data, ctx.Repo.RepoLink))

// Get last change information.
lastCommit, err := wikiRepo.GetCommitByPath(page + ".md")
if err != nil {
ctx.Handle(500, "GetCommitByPath", err)
return
}
ctx.Data["Author"] = lastCommit.Author

ctx.HTML(200, WIKI_VIEW) ctx.HTML(200, WIKI_VIEW)
} }


func WikiList(ctx *middleware.Context) {

}

func NewWiki(ctx *middleware.Context) { func NewWiki(ctx *middleware.Context) {
ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page") ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
ctx.Data["PageIsWiki"] = true ctx.Data["PageIsWiki"] = true
return return
} }


if err := ctx.Repo.Repository.AddWikiPage(form.Title, form.Content, form.Message); err != nil {
if err := ctx.Repo.Repository.AddWikiPage(ctx.User, form.Title, form.Content, form.Message); err != nil {
ctx.Handle(500, "AddWikiPage", err) ctx.Handle(500, "AddWikiPage", err)
return return
} }


ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + models.ToWikiPageName(form.Title))
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + models.ToWikiPageURL(form.Title))
} }


func EditWiki(ctx *middleware.Context) { func EditWiki(ctx *middleware.Context) {

+ 1
- 1
templates/repo/wiki/new.tmpl Vedi File

<input name="title" value="{{.title}}" autofocus required> <input name="title" value="{{.title}}" autofocus required>
</div> </div>
<div class="field"> <div class="field">
<textarea id="edit-area" name="content" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}">{{.i18n.Tr "repo.wiki.welcome"}}</textarea>
<textarea id="edit-area" name="content" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}">{{.i18n.Tr "repo.wiki.welcome"}}</textarea required>
</div> </div>
<div class="field"> <div class="field">
<input name="message" placeholder="{{.i18n.Tr "repo.wiki.default_commit_message"}}"> <input name="message" placeholder="{{.i18n.Tr "repo.wiki.default_commit_message"}}">

+ 18
- 0
templates/repo/wiki/view.tmpl Vedi File

{{template "base/head" .}}
<div class="repository wiki view">
{{template "repo/header" .}}
<div class="ui container">
{{template "repo/sidebar" .}}
<div class="ui dividing header">
{{.Title}}
<div class="ui sub header">
{{$timeSince := TimeSince .Author.When $.Lang}}
{{.i18n.Tr "repo.wiki.last_commit_info" .Author.Name $timeSince | Safe}}
</div>
</div>
<div class="ui segment markdown">
{{.Content | Str2html}}
</div>
</div>
</div>
{{template "base/footer" .}}

Loading…
Annulla
Salva