mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-11 15:04:02 +09:00
Squashed commit of the following:
commit 0afcb843d7ffd596991c4885cab768273a6eb42c Author: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Sun Jul 31 17:13:29 2016 -0600 Removed Upload stats as the upload table is just a temporary table commit 7ecd73ff5535612d79d471409173ee7f1fcfa157 Author: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Sun Jul 31 08:42:41 2016 -0600 Fix for CodeMirror mode commit c29b9ab531e2e7af0fb5db24dc17e51027dd1174 Author: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Sun Jul 31 08:03:33 2016 -0600 Made tabbing in editor use spaces commit 23af384c53206a8a40e11e45bf49d7a149c4adcd Author: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Sun Jul 31 07:56:46 2016 -0600 Fix for data-url commit cfb8a97591cb6fc0a92e49563b7b764c524db0e9 Merge: 7fc8a89991ce42Author: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Sun Jul 31 07:42:53 2016 -0600 Merge remote-tracking branch 'gogits/develop' into feature-create-and-edit-repo-file Conflicts: modules/bindata/bindata.go public/js/gogs.js commit 7fc8a89cb495478225b02d613e647f99a1489634 Merge: fd3d86c c03d040 Author: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Sun Jul 31 07:40:00 2016 -0600 Merge branch 'feature-create-and-edit-repo-file' of github.com:richmahn/gogs into feature-create-and-edit-repo-file commit fd3d86ca6bbc02cfda566a504ffd6b03db4f75ef Author: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Sun Jul 31 07:39:44 2016 -0600 Code cleanup commit c03d0401c1049eeeccc32ab1f9c3303c130be5ee Author: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Fri Jul 29 15:38:23 2016 -0600 Code cleanup commit 98e1206ccf9f9a4503c020e3a7830cf9f861dfae Author: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Thu Jul 28 18:36:01 2016 -0600 Code cleanup and fixes commit c2895dc742f25f8412879c9fa15e18f27f42f194 Author: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Thu Jul 28 18:24:04 2016 -0600 Fixes per Unknwon's requests commit 6aa7e46b21ad4c96e562daa2eac26a8fb408f8ef Merge: 889e9faad7ea88Author: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Thu Jul 28 17:13:43 2016 -0600 Merge remote-tracking branch 'gogits/develop' into feature-create-and-edit-repo-file Conflicts: modules/bindata/bindata.go modules/setting/setting.go commit 889e9faf1bd8559a4979c8f46005d488c1a234d4 Author: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Fri Jul 22 14:09:18 2016 -0600 Fix in gogs.js commit 47603edf223f147b114be65f3bd27bc1e88827a5 Merge: bb57912cf85e9eAuthor: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Fri Jul 22 14:07:36 2016 -0600 Merge remote-tracking branch 'gogits/develop' into feature-create-and-edit-repo-file Conflicts: modules/bindata/bindata.go public/js/gogs.js commit bb5791255867a71c11a77b639db050ad09c597a4 Author: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Fri Jul 22 14:02:18 2016 -0600 Update for using CodeMirror mode addon commit d10d128c51039be19e2af9c66c63db66a9f2ec6d Author: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Tue Jul 19 16:12:57 2016 -0600 Update for Edit commit 34a34982025144e3225e389f7849eb6273c1d576 Merge: fa1b7521c7dcddAuthor: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Tue Jul 19 11:52:02 2016 -0600 Merge remote-tracking branch 'gogits/develop' into feature-create-and-edit-repo-file Conflicts: modules/bindata/bindata.go commit fa1b752be29cd455c5184ddac2ffe80b3489763e Author: Richard Mahn <richard_mahn@wycliffeassociates.org> Date: Fri Jul 15 18:35:42 2016 -0600 Feature for editing, creating, uploading and deleting files
This commit is contained in:
1 parent
7e7613cdec
commit
d0a0239bac
34 files changed
+2509
-208
No files matched your search
+14
@@ -497,6 +497,20 @@ func runWeb(ctx *cli.Context) error {
|
||||
|
||||
m.Combo("/compare/*", repo.MustAllowPulls).Get(repo.CompareAndPullRequest).
|
||||
Post(bindIgnErr(auth.CreateIssueForm{}), repo.CompareAndPullRequestPost)
|
||||
|
||||
m.Group("", func() {
|
||||
m.Combo("/_edit/*").Get(repo.EditFile).
|
||||
Post(bindIgnErr(auth.EditRepoFileForm{}), repo.EditFilePost)
|
||||
m.Combo("/_new/*").Get(repo.NewFile).
|
||||
Post(bindIgnErr(auth.EditRepoFileForm{}), repo.NewFilePost)
|
||||
m.Post("/preview/*", bindIgnErr(auth.EditPreviewDiffForm{}), repo.DiffPreviewPost)
|
||||
m.Combo("/upload/*").Get(repo.UploadFile).
|
||||
Post(bindIgnErr(auth.UploadRepoFileForm{}), repo.UploadFilePost)
|
||||
m.Post("/delete/*", bindIgnErr(auth.DeleteRepoFileForm{}), repo.DeleteFilePost)
|
||||
m.Post("/branches", bindIgnErr(auth.NewBranchForm{}), repo.NewBranchPost)
|
||||
m.Post("/upload-file", repo.UploadFileToServer)
|
||||
m.Post("/upload-remove", bindIgnErr(auth.RemoveUploadFileForm{}), repo.RemoveUploadFileFromServer)
|
||||
}, context.RepoRef(), context.RepoAssignment(), reqRepoWriter)
|
||||
}, reqSignIn, context.RepoAssignment(), repo.MustBeNotBare)
|
||||
|
||||
m.Group("/:username/:reponame", func() {
|
||||
|
||||
@@ -20,6 +20,26 @@ MAX_CREATION_LIMIT = -1
|
||||
; Patch test queue length, make it as large as possible
|
||||
PULL_REQUEST_QUEUE_LENGTH = 10000
|
||||
|
||||
[editor]
|
||||
; List of file extensions that should have line wraps in the CodeMirror editor
|
||||
; Separate extensions with a comma. To line wrap files w/o extension, just put a comma
|
||||
LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd,
|
||||
; Valid file modes that have a preview API associated with them, such as api/v1/markdown
|
||||
; Separate values by commas. Preview tab in edit mode won't show if the file extension doesn't match
|
||||
PREVIEW_TAB_APIS = markdown
|
||||
|
||||
[upload]
|
||||
; Whether repository file uploads are enabled. Defaults to `true`
|
||||
ENABLE_UPLOADS = true
|
||||
; Path for uploads. Defaults to `data/tmp/uploads` (tmp gets deleted on gogs restart)
|
||||
TEMP_PATH = data/tmp/uploads
|
||||
; One or more allowed types, e.g. image/jpeg|image/png. Nothing means any file type
|
||||
ALLOWED_TYPES =
|
||||
; Max size of each file in MB. Defaults to 32MB
|
||||
FILE_MAX_SIZE = 32
|
||||
; Max number of files per upload. Defaults to 10
|
||||
MAX_FILES = 10
|
||||
|
||||
[ui]
|
||||
; Number of repositories that are showed in one explore page
|
||||
EXPLORE_PAGING_NUM = 20
|
||||
@@ -54,6 +74,9 @@ ENABLE_HARD_LINE_BREAK = false
|
||||
; List of custom URL-Schemes that are allowed as links when rendering Markdown
|
||||
; for example git,magnet
|
||||
CUSTOM_URL_SCHEMES =
|
||||
; List of file extensions that should be rendered/edited as Markdown
|
||||
; Separate extensions with a comma. To render files w/o extension as markdown, just put a comma
|
||||
MD_FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd
|
||||
|
||||
[server]
|
||||
PROTOCOL = http
|
||||
|
||||
@@ -189,6 +189,13 @@ TeamName = Team name
|
||||
AuthName = Authorization name
|
||||
AdminEmail = Admin email
|
||||
|
||||
NewBranchName = New branch name
|
||||
CommitSummary = Commit summary
|
||||
CommitMessage = Commit message
|
||||
CommitChoice = Commit choice
|
||||
TreeName = File path
|
||||
Content = Content
|
||||
|
||||
require_error = ` cannot be empty.`
|
||||
alpha_dash_error = ` must be valid alpha or numeric or dash(-_) characters.`
|
||||
alpha_dash_dot_error = ` must be valid alpha or numeric or dash(-_) or dot characters.`
|
||||
@@ -419,6 +426,51 @@ file_view_raw = View Raw
|
||||
file_permalink = Permalink
|
||||
file_too_large = This file is too large to be shown
|
||||
|
||||
cancel = Cancel
|
||||
cancel_lower = cancel
|
||||
or = or
|
||||
new_file = New file
|
||||
upload_files = Upload files
|
||||
find_file = Find file
|
||||
commit_changes = Commit Changes
|
||||
default_commit_message = Add an optional extended description...
|
||||
last_commit_info = %s edited this file %s
|
||||
delete_this_file = Delete this file
|
||||
edit_this_file = Edit this file
|
||||
edit_file = Edit file
|
||||
delete_confirm_message = Are you sure you want to delete this file?
|
||||
delete_commit_message = Write a note about this delete (optional)
|
||||
file_editing_no_longer_exists = The file you are editing no longer exists in the repository
|
||||
file_already_exists = A file by that name already exists
|
||||
unable_to_update_file = Unable to update this file, error occurred
|
||||
add = Add
|
||||
update = Update
|
||||
filename_cannot_be_empty = Filename cannot be empty
|
||||
directory_is_a_file = One of the directories in the path is already a file in this repository
|
||||
filename_is_a_directory = The filename given is an existing directory in the repository
|
||||
must_be_on_branch = You must be on a branch to make or propose changes to this file
|
||||
must_be_writer = You must have write access to make or propose changes to this file
|
||||
cannot_edit_binary_files = Cannot edit binary files
|
||||
filename_help = To add directory, just type it and press /. To remove a directory, go to the beginning of the field and press backspace.
|
||||
fork_before_edit = You must fork this before editing
|
||||
branch_already_exists = Branch already exists
|
||||
create_new_branch = Create a %s for this commit and start a pull request.
|
||||
new_branch = new branch
|
||||
commit_directly_to_this_branch = Commit directly to the %s branch.
|
||||
create_branch = Create branch
|
||||
from = from
|
||||
upload_file = Upload file
|
||||
add_files_to_dir = Add files to %s
|
||||
unable_to_upload_files = Unable to upload files, an error occurred.
|
||||
add_subdir = Add subdirectory...
|
||||
name_your_file = Name your file...
|
||||
user_has_committed_since_you_started_editing = %s has committed since you started editing.
|
||||
see_what_changed = See what changed.
|
||||
pressing_commit_again_will_overwrite_those_changes = Pressing '%s' again will overwrite those changes.
|
||||
copy_file_path_to_clipboard = Copy file path to clipboard
|
||||
preview_changes = Preview Changes
|
||||
no_changes_to_show = There are no changes to show.
|
||||
|
||||
commits.commits = Commits
|
||||
commits.search = Search commits
|
||||
commits.find = Find
|
||||
|
||||
@@ -417,6 +417,19 @@ func (err ErrInvalidTagName) Error() string {
|
||||
return fmt.Sprintf("release tag name is not valid [tag_name: %s]", err.TagName)
|
||||
}
|
||||
|
||||
type ErrRepoFileAlreadyExist struct {
|
||||
FileName string
|
||||
}
|
||||
|
||||
func IsErrRepoFileAlreadyExist(err error) bool {
|
||||
_, ok := err.(ErrRepoFileAlreadyExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrRepoFileAlreadyExist) Error() string {
|
||||
return fmt.Sprintf("repository file already exists [file name: %s]", err.FileName)
|
||||
}
|
||||
|
||||
// __________ .__
|
||||
// \______ \____________ ____ ____ | |__
|
||||
// | | _/\_ __ \__ \ / \_/ ___\| | \
|
||||
@@ -628,3 +641,27 @@ func IsErrTeamAlreadyExist(err error) bool {
|
||||
func (err ErrTeamAlreadyExist) Error() string {
|
||||
return fmt.Sprintf("team already exists [org_id: %d, name: %s]", err.OrgID, err.Name)
|
||||
}
|
||||
|
||||
// ____ ___ .__ .___
|
||||
// | | \______ | | _________ __| _/
|
||||
// | | /\____ \| | / _ \__ \ / __ |
|
||||
// | | / | |_> > |_( <_> ) __ \_/ /_/ |
|
||||
// |______/ | __/|____/\____(____ /\____ |
|
||||
// |__| \/ \/
|
||||
//
|
||||
|
||||
type ErrUploadNotExist struct {
|
||||
ID int64
|
||||
UUID string
|
||||
UserID int64
|
||||
RepoID int64
|
||||
}
|
||||
|
||||
func IsErrUploadNotExist(err error) bool {
|
||||
_, ok := err.(ErrAttachmentNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUploadNotExist) Error() string {
|
||||
return fmt.Sprintf("attachment does not exist [id: %d, uuid: %s]", err.ID, err.UUID)
|
||||
}
|
||||
+5
-10
@@ -639,23 +639,18 @@ func newIssue(e *xorm.Session, repo *Repository, issue *Issue, labelIDs []int64,
|
||||
}
|
||||
|
||||
// Check attachments.
|
||||
attachments := make([]*Attachment, 0, len(uuids))
|
||||
for _, uuid := range uuids {
|
||||
attach, err := getAttachmentByUUID(e, uuid)
|
||||
attachment, err := getAttachmentByUUID(e, uuid)
|
||||
if err != nil {
|
||||
if IsErrAttachmentNotExist(err) {
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("getAttachmentByUUID[%s]: %v", uuid, err)
|
||||
}
|
||||
attachments = append(attachments, attach)
|
||||
}
|
||||
|
||||
for i := range attachments {
|
||||
attachments[i].IssueID = issue.ID
|
||||
attachment.IssueID = issue.ID
|
||||
// No assign value could be 0, so ignore AllCols().
|
||||
if _, err = e.Id(attachments[i].ID).Update(attachments[i]); err != nil {
|
||||
return fmt.Errorf("update attachment[%d]: %v", attachments[i].ID, err)
|
||||
if _, err = e.Id(attachment.ID).Update(attachment); err != nil {
|
||||
return fmt.Errorf("update attachment[%d]: %v", attachment.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1728,7 +1723,7 @@ func DeleteAttachments(attachments []*Attachment, remove bool) (int, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := x.Delete(a.ID); err != nil {
|
||||
if _, err := x.Delete(a); err != nil {
|
||||
return i, err
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -354,7 +354,7 @@ func (pr *PullRequest) testPatch() (err error) {
|
||||
|
||||
log.Trace("PullRequest[%d].testPatch (patchPath): %s", pr.ID, patchPath)
|
||||
|
||||
if err := pr.BaseRepo.UpdateLocalCopy(); err != nil {
|
||||
if err := pr.BaseRepo.UpdateLocalCopy(pr.BaseRepo.DefaultBranch); err != nil {
|
||||
return fmt.Errorf("UpdateLocalCopy: %v", err)
|
||||
}
|
||||
|
||||
|
||||
+439
-4
@@ -9,7 +9,9 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
@@ -28,6 +30,7 @@ import (
|
||||
|
||||
git "github.com/gogits/git-module"
|
||||
api "github.com/gogits/go-gogs-client"
|
||||
gouuid "github.com/satori/go.uuid"
|
||||
|
||||
"github.com/gogits/gogs/modules/bindata"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
@@ -435,16 +438,25 @@ func (repo *Repository) LocalCopyPath() string {
|
||||
return path.Join(setting.AppDataPath, "tmp/local", com.ToStr(repo.ID))
|
||||
}
|
||||
|
||||
func updateLocalCopy(repoPath, localPath string) error {
|
||||
func updateLocalCopy(repoPath, localPath, branch string) error {
|
||||
if !com.IsExist(localPath) {
|
||||
if err := git.Clone(repoPath, localPath, git.CloneRepoOptions{
|
||||
Timeout: time.Duration(setting.Git.Timeout.Clone) * time.Second,
|
||||
Branch: branch,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("Clone: %v", err)
|
||||
}
|
||||
} else {
|
||||
if err := git.Checkout(localPath, git.CheckoutOptions{
|
||||
Branch: branch,
|
||||
Timeout: time.Duration(setting.Git.Timeout.Pull) * time.Second,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("Checkout: %v", err)
|
||||
}
|
||||
if err := git.Pull(localPath, git.PullRemoteOptions{
|
||||
All: true,
|
||||
All: false,
|
||||
Remote: "origin",
|
||||
Branch: branch,
|
||||
Timeout: time.Duration(setting.Git.Timeout.Pull) * time.Second,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("Pull: %v", err)
|
||||
@@ -454,8 +466,8 @@ func updateLocalCopy(repoPath, localPath string) error {
|
||||
}
|
||||
|
||||
// UpdateLocalCopy makes sure the local copy of repository is up-to-date.
|
||||
func (repo *Repository) UpdateLocalCopy() error {
|
||||
return updateLocalCopy(repo.RepoPath(), repo.LocalCopyPath())
|
||||
func (repo *Repository) UpdateLocalCopy(branch string) error {
|
||||
return updateLocalCopy(repo.RepoPath(), repo.LocalCopyPath(), branch)
|
||||
}
|
||||
|
||||
// PatchPath returns corresponding patch file path of repository by given issue ID.
|
||||
@@ -2255,3 +2267,426 @@ func (repo *Repository) GetForks() ([]*Repository, error) {
|
||||
forks := make([]*Repository, 0, repo.NumForks)
|
||||
return forks, x.Find(&forks, &Repository{ForkID: repo.ID})
|
||||
}
|
||||
|
||||
// ___________ .___.__ __ ___________.__.__
|
||||
// \_ _____/ __| _/|__|/ |_ \_ _____/|__| | ____
|
||||
// | __)_ / __ | | \ __\ | __) | | | _/ __ \
|
||||
// | \/ /_/ | | || | | \ | | |_\ ___/
|
||||
// /_______ /\____ | |__||__| \___ / |__|____/\___ >
|
||||
// \/ \/ \/ \/
|
||||
|
||||
var repoWorkingPool = &workingPool{
|
||||
pool: make(map[string]*sync.Mutex),
|
||||
count: make(map[string]int),
|
||||
}
|
||||
|
||||
func (repo *Repository) LocalRepoPath() string {
|
||||
return path.Join(setting.AppDataPath, "tmp/local-repo", com.ToStr(repo.ID))
|
||||
}
|
||||
|
||||
// UpdateLocalRepo makes sure the local copy of repository is up-to-date.
|
||||
func (repo *Repository) UpdateLocalRepo(branchName string) error {
|
||||
return updateLocalCopy(repo.RepoPath(), repo.LocalRepoPath(), branchName)
|
||||
}
|
||||
|
||||
// DiscardLocalRepoChanges makes sure the local copy of repository is the same as the source
|
||||
func (repo *Repository) DiscardLocalRepoChanges(branchName string) error {
|
||||
return discardLocalRepoChanges(repo.LocalRepoPath(), branchName)
|
||||
}
|
||||
|
||||
// discardLocalRepoChanges discards local commits make sure
|
||||
// it is even to remote branch when local copy exists.
|
||||
func discardLocalRepoChanges(localPath string, branch string) error {
|
||||
if !com.IsExist(localPath) {
|
||||
return nil
|
||||
}
|
||||
// No need to check if nothing in the repository.
|
||||
if !git.IsBranchExist(localPath, branch) {
|
||||
return nil
|
||||
}
|
||||
if err := git.ResetHEAD(localPath, true, "origin/"+branch); err != nil {
|
||||
return fmt.Errorf("ResetHEAD: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckoutNewBranch checks out a new branch from the given branch name
|
||||
func (repo *Repository) CheckoutNewBranch(oldBranchName, newBranchName string) error {
|
||||
return checkoutNewBranch(repo.RepoPath(), repo.LocalRepoPath(), oldBranchName, newBranchName)
|
||||
}
|
||||
|
||||
func checkoutNewBranch(repoPath, localPath, oldBranch, newBranch string) error {
|
||||
if !com.IsExist(localPath) {
|
||||
if err := updateLocalCopy(repoPath, localPath, oldBranch); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := git.Checkout(localPath, git.CheckoutOptions{
|
||||
Branch: newBranch,
|
||||
OldBranch: oldBranch,
|
||||
Timeout: time.Duration(setting.Git.Timeout.Pull) * time.Second,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("Checkout New Branch: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// updateRepoFile adds new file to repository.
|
||||
func (repo *Repository) UpdateRepoFile(doer *User, oldBranchName, branchName, oldTreeName, treeName, content, message string, isNewFile bool) (err error) {
|
||||
repoWorkingPool.CheckIn(com.ToStr(repo.ID))
|
||||
defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
|
||||
|
||||
if err = repo.DiscardLocalRepoChanges(oldBranchName); err != nil {
|
||||
return fmt.Errorf("discardLocalRepoChanges: %s - %v", oldBranchName, err)
|
||||
} else if err = repo.UpdateLocalRepo(oldBranchName); err != nil {
|
||||
return fmt.Errorf("UpdateLocalRepo: %s - %v", oldBranchName, err)
|
||||
}
|
||||
|
||||
if oldBranchName != branchName {
|
||||
if err := repo.CheckoutNewBranch(oldBranchName, branchName); err != nil {
|
||||
return fmt.Errorf("CheckoutNewBranch: %s - %s: %v", oldBranchName, branchName, err)
|
||||
}
|
||||
}
|
||||
|
||||
localPath := repo.LocalRepoPath()
|
||||
filePath := path.Join(localPath, treeName)
|
||||
|
||||
if len(message) == 0 {
|
||||
if isNewFile {
|
||||
message = "Add '" + treeName + "'"
|
||||
} else {
|
||||
message = "Update '" + treeName + "'"
|
||||
}
|
||||
}
|
||||
|
||||
os.MkdirAll(filepath.Dir(filePath), os.ModePerm)
|
||||
|
||||
// If new file, make sure it doesn't exist; if old file, move if file name change
|
||||
if isNewFile {
|
||||
if com.IsExist(filePath) {
|
||||
return ErrRepoFileAlreadyExist{filePath}
|
||||
}
|
||||
} else if oldTreeName != "" && treeName != "" && treeName != oldTreeName {
|
||||
if err = git.MoveFile(localPath, oldTreeName, treeName); err != nil {
|
||||
return fmt.Errorf("MoveFile: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err = ioutil.WriteFile(filePath, []byte(content), 0666); err != nil {
|
||||
return fmt.Errorf("WriteFile: %v", err)
|
||||
}
|
||||
|
||||
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", branchName); err != nil {
|
||||
return fmt.Errorf("Push: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (repo *Repository) GetPreviewDiff(repoPath, branchName, treeName, text string, maxlines, maxchars, maxfiles int) (diff *Diff, err error) {
|
||||
repoWorkingPool.CheckIn(com.ToStr(repo.ID))
|
||||
defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
|
||||
|
||||
if err = repo.DiscardLocalRepoChanges(branchName); err != nil {
|
||||
return nil, fmt.Errorf("discardLocalRepoChanges: %s - %v", branchName, err)
|
||||
} else if err = repo.UpdateLocalRepo(branchName); err != nil {
|
||||
return nil, fmt.Errorf("UpdateLocalRepo: %s - %v", branchName, err)
|
||||
}
|
||||
|
||||
localPath := repo.LocalRepoPath()
|
||||
filePath := path.Join(localPath, treeName)
|
||||
|
||||
os.MkdirAll(filepath.Dir(filePath), os.ModePerm)
|
||||
|
||||
if err = ioutil.WriteFile(filePath, []byte(text), 0666); err != nil {
|
||||
return nil, fmt.Errorf("WriteFile: %v", err)
|
||||
}
|
||||
|
||||
var cmd *exec.Cmd
|
||||
cmd = exec.Command("git", "diff", treeName)
|
||||
cmd.Dir = localPath
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("StdoutPipe: %v", err)
|
||||
}
|
||||
|
||||
if err = cmd.Start(); err != nil {
|
||||
return nil, fmt.Errorf("Start: %v", err)
|
||||
}
|
||||
|
||||
pid := process.Add(fmt.Sprintf("GetDiffRange (%s)", repoPath), cmd)
|
||||
defer process.Remove(pid)
|
||||
|
||||
diff, err = ParsePatch(maxlines, maxchars, maxfiles, stdout)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ParsePatch: %v", err)
|
||||
}
|
||||
|
||||
if err = cmd.Wait(); err != nil {
|
||||
return nil, fmt.Errorf("Wait: %v", err)
|
||||
}
|
||||
|
||||
return diff, nil
|
||||
}
|
||||
|
||||
// ________ .__ __ ___________.__.__
|
||||
// \______ \ ____ | | _____/ |_ ____ \_ _____/|__| | ____
|
||||
// | | \_/ __ \| | _/ __ \ __\/ __ \ | __) | | | _/ __ \
|
||||
// | ` \ ___/| |_\ ___/| | \ ___/ | \ | | |_\ ___/
|
||||
// /_______ /\___ >____/\___ >__| \___ > \___ / |__|____/\___ >
|
||||
// \/ \/ \/ \/ \/ \/
|
||||
//
|
||||
|
||||
func (repo *Repository) DeleteRepoFile(doer *User, branch, treeName, message string) (err error) {
|
||||
repoWorkingPool.CheckIn(com.ToStr(repo.ID))
|
||||
defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
|
||||
|
||||
localPath := repo.LocalRepoPath()
|
||||
if err = discardLocalRepoChanges(localPath, branch); err != nil {
|
||||
return fmt.Errorf("discardLocalRepoChanges: %v", err)
|
||||
} else if err = repo.UpdateLocalRepo(branch); err != nil {
|
||||
return fmt.Errorf("UpdateLocalRepo: %v", err)
|
||||
}
|
||||
|
||||
filePath := path.Join(localPath, treeName)
|
||||
os.Remove(filePath)
|
||||
|
||||
if len(message) == 0 {
|
||||
message = "Delete file '" + treeName + "'"
|
||||
}
|
||||
|
||||
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", branch); err != nil {
|
||||
return fmt.Errorf("Push: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ____ ___ .__ .___ ___________.___.__
|
||||
// | | \______ | | _________ __| _/ \_ _____/| | | ____ ______
|
||||
// | | /\____ \| | / _ \__ \ / __ | | __) | | | _/ __ \ / ___/
|
||||
// | | / | |_> > |_( <_> ) __ \_/ /_/ | | \ | | |_\ ___/ \___ \
|
||||
// |______/ | __/|____/\____(____ /\____ | \___ / |___|____/\___ >____ >
|
||||
// |__| \/ \/ \/ \/ \/
|
||||
//
|
||||
|
||||
// uploadRepoFiles uploads new files to repository.
|
||||
func (repo *Repository) UploadRepoFiles(doer *User, oldBranchName, branchName, treeName, message string, uuids []string) (err error) {
|
||||
repoWorkingPool.CheckIn(com.ToStr(repo.ID))
|
||||
defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
|
||||
|
||||
localPath := repo.LocalRepoPath()
|
||||
|
||||
if err = discardLocalRepoChanges(localPath, oldBranchName); err != nil {
|
||||
return fmt.Errorf("discardLocalRepoChanges: %v", err)
|
||||
} else if err = repo.UpdateLocalRepo(oldBranchName); err != nil {
|
||||
return fmt.Errorf("UpdateLocalRepo: %v", err)
|
||||
}
|
||||
|
||||
if oldBranchName != branchName {
|
||||
repo.CheckoutNewBranch(oldBranchName, branchName)
|
||||
}
|
||||
|
||||
dirPath := path.Join(localPath, treeName)
|
||||
os.MkdirAll(dirPath, os.ModePerm)
|
||||
|
||||
// Copy uploaded files into repository.
|
||||
for _, uuid := range uuids {
|
||||
upload, err := getUpload(uuid, doer.ID, repo.ID)
|
||||
if err != nil {
|
||||
if IsErrUploadNotExist(err) {
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("getUpload[%s]: %v", uuid, err)
|
||||
}
|
||||
uuidPath := upload.LocalPath()
|
||||
filePath := dirPath + "/" + upload.Name
|
||||
if err := os.Rename(uuidPath, filePath); err != nil {
|
||||
DeleteUpload(upload, true)
|
||||
return fmt.Errorf("Rename[%s -> %s]: %v", uuidPath, filePath, err)
|
||||
}
|
||||
DeleteUpload(upload, false) // false because we have moved the file
|
||||
}
|
||||
|
||||
if len(message) == 0 {
|
||||
message = "Add files to '" + treeName + "'"
|
||||
}
|
||||
|
||||
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", branchName); err != nil {
|
||||
return fmt.Errorf("Push: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Upload represent a uploaded file to a repo to be deleted when moved
|
||||
type Upload struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UUID string `xorm:"uuid UNIQUE"`
|
||||
UID int64 `xorm:"INDEX"`
|
||||
RepoID int64 `xorm:"INDEX"`
|
||||
Name string
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64
|
||||
}
|
||||
|
||||
func (u *Upload) BeforeInsert() {
|
||||
u.CreatedUnix = time.Now().UTC().Unix()
|
||||
}
|
||||
|
||||
func (u *Upload) AfterSet(colName string, _ xorm.Cell) {
|
||||
switch colName {
|
||||
case "created_unix":
|
||||
u.Created = time.Unix(u.CreatedUnix, 0).Local()
|
||||
}
|
||||
}
|
||||
|
||||
// UploadLocalPath returns where uploads is stored in local file system based on given UUID.
|
||||
func UploadLocalPath(uuid string) string {
|
||||
return path.Join(setting.UploadTempPath, uuid[0:1], uuid[1:2], uuid)
|
||||
}
|
||||
|
||||
// LocalPath returns where uploads are temporarily stored in local file system.
|
||||
func (upload *Upload) LocalPath() string {
|
||||
return UploadLocalPath(upload.UUID)
|
||||
}
|
||||
|
||||
// NewUpload creates a new upload object.
|
||||
func NewUpload(name string, buf []byte, file multipart.File, userId, repoId int64) (_ *Upload, err error) {
|
||||
up := &Upload{
|
||||
UUID: gouuid.NewV4().String(),
|
||||
Name: name,
|
||||
UID: userId,
|
||||
RepoID: repoId,
|
||||
}
|
||||
|
||||
if err = os.MkdirAll(path.Dir(up.LocalPath()), os.ModePerm); err != nil {
|
||||
return nil, fmt.Errorf("MkdirAll: %v", err)
|
||||
}
|
||||
|
||||
fw, err := os.Create(up.LocalPath())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Create: %v", err)
|
||||
}
|
||||
defer fw.Close()
|
||||
|
||||
if _, err = fw.Write(buf); err != nil {
|
||||
return nil, fmt.Errorf("Write: %v", err)
|
||||
} else if _, err = io.Copy(fw, file); err != nil {
|
||||
return nil, fmt.Errorf("Copy: %v", err)
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
if err := sess.Begin(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := sess.Insert(up); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return up, sess.Commit()
|
||||
}
|
||||
|
||||
// RemoveUpload removes the file by UUID
|
||||
func RemoveUpload(uuid string, userId, repoId int64) (err error) {
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
upload, err := getUpload(uuid, userId, repoId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getUpload[%s]: %v", uuid, err)
|
||||
}
|
||||
|
||||
if err := DeleteUpload(upload, true); err != nil {
|
||||
return fmt.Errorf("DeleteUpload[%s]: %v", uuid, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getUpload(uuid string, userID, repoID int64) (*Upload, error) {
|
||||
up := &Upload{UUID: uuid, UID: userID, RepoID: repoID}
|
||||
has, err := x.Get(up)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, ErrUploadNotExist{0, uuid, userID, repoID}
|
||||
}
|
||||
return up, nil
|
||||
}
|
||||
|
||||
// GetUpload returns Upload by given UUID.
|
||||
func GetUpload(uuid string, userId, repoId int64) (*Upload, error) {
|
||||
return getUpload(uuid, userId, repoId)
|
||||
}
|
||||
|
||||
// DeleteUpload deletes the given upload
|
||||
func DeleteUpload(u *Upload, remove bool) error {
|
||||
_, err := DeleteUploads([]*Upload{u}, remove)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteUploads deletes the given uploads
|
||||
func DeleteUploads(uploads []*Upload, remove bool) (int, error) {
|
||||
for i, u := range uploads {
|
||||
if remove {
|
||||
if err := os.Remove(u.LocalPath()); err != nil {
|
||||
return i, err
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := x.Delete(u); err != nil {
|
||||
return i, err
|
||||
}
|
||||
}
|
||||
|
||||
return len(uploads), nil
|
||||
}
|
||||
|
||||
// __________ .__
|
||||
// \______ \____________ ____ ____ | |__
|
||||
// | | _/\_ __ \__ \ / \_/ ___\| | \
|
||||
// | | \ | | \// __ \| | \ \___| Y \
|
||||
// |______ / |__| (____ /___| /\___ >___| /
|
||||
// \/ \/ \/ \/ \/
|
||||
//
|
||||
|
||||
func (repo *Repository) CreateNewBranch(doer *User, oldBranchName, branchName string) (err error) {
|
||||
repoWorkingPool.CheckIn(com.ToStr(repo.ID))
|
||||
defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
|
||||
|
||||
localPath := repo.LocalRepoPath()
|
||||
|
||||
if err = discardLocalRepoChanges(localPath, oldBranchName); err != nil {
|
||||
return fmt.Errorf("discardLocalRepoChanges: %v", err)
|
||||
} else if err = repo.UpdateLocalRepo(oldBranchName); err != nil {
|
||||
return fmt.Errorf("UpdateLocalRepo: %v", err)
|
||||
}
|
||||
|
||||
if err = repo.CheckoutNewBranch(oldBranchName, branchName); err != nil {
|
||||
return fmt.Errorf("CreateNewBranch: %v", err)
|
||||
}
|
||||
|
||||
if err = git.Push(localPath, "origin", branchName); err != nil {
|
||||
return fmt.Errorf("Push: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
+1
-39
@@ -21,44 +21,6 @@ import (
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
// 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),
|
||||
@@ -117,7 +79,7 @@ func (repo *Repository) LocalWikiPath() string {
|
||||
|
||||
// UpdateLocalWiki makes sure the local copy of repository wiki is up-to-date.
|
||||
func (repo *Repository) UpdateLocalWiki() error {
|
||||
return updateLocalCopy(repo.WikiPath(), repo.LocalWikiPath())
|
||||
return updateLocalCopy(repo.WikiPath(), repo.LocalWikiPath(), "")
|
||||
}
|
||||
|
||||
// discardLocalWikiChanges discards local commits make sure
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright 2015 The Gogs 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 models
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// 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]--
|
||||
}
|
||||
}
|
||||
@@ -169,7 +169,7 @@ type CreateIssueForm struct {
|
||||
MilestoneID int64
|
||||
AssigneeID int64
|
||||
Content string
|
||||
Attachments []string
|
||||
Files []string
|
||||
}
|
||||
|
||||
func (f *CreateIssueForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
@@ -177,9 +177,9 @@ func (f *CreateIssueForm) Validate(ctx *macaron.Context, errs binding.Errors) bi
|
||||
}
|
||||
|
||||
type CreateCommentForm struct {
|
||||
Content string
|
||||
Status string `binding:"OmitEmpty;In(reopen,close)"`
|
||||
Attachments []string
|
||||
Content string
|
||||
Status string `binding:"OmitEmpty;In(reopen,close)"`
|
||||
Files []string
|
||||
}
|
||||
|
||||
func (f *CreateCommentForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
@@ -269,3 +269,91 @@ type NewWikiForm struct {
|
||||
func (f *NewWikiForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// ___________ .___.__ __
|
||||
// \_ _____/ __| _/|__|/ |_
|
||||
// | __)_ / __ | | \ __\
|
||||
// | \/ /_/ | | || |
|
||||
// /_______ /\____ | |__||__|
|
||||
// \/ \/
|
||||
|
||||
type EditRepoFileForm struct {
|
||||
TreeName string `binding:"Required;MaxSize(500)"`
|
||||
Content string `binding:"Required"`
|
||||
CommitSummary string `binding:"MaxSize(100)`
|
||||
CommitMessage string
|
||||
CommitChoice string `binding:"Required;MaxSize(50)"`
|
||||
NewBranchName string `binding:"AlphaDashDot;MaxSize(100)"`
|
||||
LastCommit string
|
||||
}
|
||||
|
||||
func (f *EditRepoFileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type EditPreviewDiffForm struct {
|
||||
Content string
|
||||
}
|
||||
|
||||
func (f *EditPreviewDiffForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// ____ ___ .__ .___
|
||||
// | | \______ | | _________ __| _/
|
||||
// | | /\____ \| | / _ \__ \ / __ |
|
||||
// | | / | |_> > |_( <_> ) __ \_/ /_/ |
|
||||
// |______/ | __/|____/\____(____ /\____ |
|
||||
// |__| \/ \/
|
||||
//
|
||||
|
||||
type UploadRepoFileForm struct {
|
||||
TreeName string `binding:MaxSize(500)"`
|
||||
CommitSummary string `binding:"MaxSize(100)`
|
||||
CommitMessage string
|
||||
CommitChoice string `binding:"Required;MaxSize(50)"`
|
||||
NewBranchName string `binding:"AlphaDashDot;MaxSize(100)"`
|
||||
Files []string
|
||||
}
|
||||
|
||||
func (f *UploadRepoFileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type RemoveUploadFileForm struct {
|
||||
File string `binding:"Required;MaxSize(50)"`
|
||||
}
|
||||
|
||||
func (f *RemoveUploadFileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// ________ .__ __
|
||||
// \______ \ ____ | | _____/ |_ ____
|
||||
// | | \_/ __ \| | _/ __ \ __\/ __ \
|
||||
// | ` \ ___/| |_\ ___/| | \ ___/
|
||||
// /_______ /\___ >____/\___ >__| \___ >
|
||||
// \/ \/ \/ \/
|
||||
|
||||
type DeleteRepoFileForm struct {
|
||||
CommitSummary string `binding:"MaxSize(100)`
|
||||
}
|
||||
|
||||
func (f *DeleteRepoFileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// __________ .__
|
||||
// \______ \____________ ____ ____ | |__
|
||||
// | | _/\_ __ \__ \ / \_/ ___\| | \
|
||||
// | | \ | | \// __ \| | \ \___| Y \
|
||||
// |______ / |__| (____ /___| /\___ >___| /
|
||||
// \/ \/ \/ \/ \/
|
||||
type NewBranchForm struct {
|
||||
OldBranchName string `binding:"Required;MaxSize(100)"`
|
||||
BranchName string `binding:"Required;MaxSize(100)"`
|
||||
}
|
||||
|
||||
func (f *NewBranchForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
@@ -286,7 +286,7 @@ func (fi bindataFileInfo) Sys() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
var _confAppIni = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xb4\x5a\x5b\x6f\x23\xc9\x75\x7e\xef\x5f\x51\xab\xcd\x66\x34\x41\x93\xba\x8d\x34\x5a\xd9\x72\x96\x22\x9b\x14\x3d\xbc\xb9\x9b\x9a\xd9\xd9\x81\xd0\x6a\xb1\x8b\x64\xaf\x9a\xdd\xdc\xae\xa6\x34\x5a\x04\x81\x8d\x3c\xe4\x02\x04\x79\x48\x90\x20\x40\x10\x24\x0f\x89\x01\xe7\x66\x23\x2f\xde\x64\x93\x97\x4d\xde\x67\xff\x83\xb3\x8e\x9f\xfc\x17\xf2\x9d\x53\xd5\x64\x53\xa3\x55\xbc\x40\x62\xef\x88\x7d\xa9\x3a\x75\xea\x5c\xbf\x73\xaa\xdf\x15\x3d\xe7\xb9\xe3\x0a\xfe\xd3\xed\x37\xda\xcd\x97\x62\x78\xda\xf6\x44\xb3\xdd\x71\xac\x77\xc5\xa0\xe3\xd4\x3c\x47\x74\x6b\xcf\x1c\x51\x3f\xad\xf5\x5a\x8e\x27\xfa\x3d\x51\xef\xbb\xae\xe3\x0d\xfa\xbd\x46\xbb\xd7\x12\xf5\x33\x6f\xd8\xef\xe2\x61\xaf\xd9\x6e\xe9\x99\xd6\xb7\x44\x6d\x3e\x17\x49\x30\x93\x22\x9f\x06\xb9\x50\xd3\xf4\x46\x89\x34\x11\xf2\x5a\x66\xb7\x62\x1e\x4c\xf0\x22\xca\x63\x69\xd5\x06\x03\xbf\x57\xeb\x3a\xe2\x58\xb4\xd2\x89\x3a\xc2\x5f\xd1\x8a\x72\xe1\xc9\xec\x3a\x1a\x49\x50\xaa\x4f\x83\x04\xc3\xf1\x2c\x1a\x8b\xdb\x74\x21\xb2\x45\x22\xe2\x74\x14\xc4\xf1\xad\xe5\x9e\xf5\xfc\x33\x0f\xdc\x1f\x8b\x49\x94\x63\xb4\x13\xe5\x53\x99\x89\x8d\x50\x5e\x6f\xd8\x62\x63\x9e\xa5\xe1\x86\x48\xf1\x20\x97\x2a\xc7\x93\x50\x8e\x83\x45\x0c\x5a\x4a\x8f\x61\x0a\xd8\x3a\x31\x80\x7b\xcb\x7a\x95\xc9\x79\xaa\xa2\x3c\xcd\x6e\xcf\x2d\xb7\xdf\x1f\x8a\x63\xcb\xab\xbb\xed\xc1\xd0\x1f\xbe\x1c\xd0\xb0\xcb\x40\x4d\xb1\x52\xc3\x50\xaa\xf5\xbc\xb6\x18\x4d\x83\x4c\xc9\xdc\xa2\x1b\x1f\xa2\x72\x3d\x87\x26\x7e\x4b\x34\xd3\x6c\x24\xcd\xb6\x13\x79\x23\x56\xd4\x45\x9e\x8a\x4b\x29\xe6\x59\x74\x1d\xe4\xd2\x6a\xf6\xdd\xba\xe3\x0f\xdc\xf6\xf3\xda\x90\x56\x19\x07\xb1\xa2\xed\xb7\xe2\xf4\x32\x88\xc5\x2c\x78\x1d\xcd\x16\x33\x31\xca\x64\x90\x47\x90\x64\x1c\xcd\x20\x92\x74\x5c\xa6\x38\xc7\xce\x17\x4a\x66\xb6\xa8\xec\x88\x99\x0c\x12\x25\x92\x54\x8f\xb4\xba\xb5\x0f\xfd\xba\xeb\xd4\x86\xed\x7e\xcf\xef\xb4\xbb\x6d\xf0\x87\x61\x58\x61\x10\xe4\xa3\xa9\x20\xf9\x88\x4f\x16\x72\x21\x45\x2c\x93\x49\x3e\xb5\xb1\xe6\x15\xcb\x3d\x50\x22\x0e\x32\xe8\x00\x17\x58\x4b\x45\x97\x50\xdc\xe0\xac\xd3\xf1\x5d\xe7\x7b\x67\x8e\x37\xf4\xf1\xf7\xcc\xf1\x3b\x4e\xaf\x35\x3c\x05\xd9\x9d\x6d\xfc\x0f\xa2\x5c\x44\xe7\xa0\xdf\x5b\xcc\x2e\xc1\x58\x99\xd5\x48\x2a\x6d\x18\x41\x26\xd9\x38\x64\x28\xa2\x04\x06\x02\x51\xbd\x9e\xc7\x29\x9e\x92\x8d\x58\xce\x87\x83\x4e\xdf\x85\x58\x6a\x2d\x98\x9a\xdf\x3b\xeb\x82\xfa\xee\xf6\x1a\xd1\x48\xa9\xc5\xd7\x93\x63\x32\x6d\xcf\x3b\xbb\x43\x64\x67\x9d\xc8\x52\xbc\xe9\x0c\xc2\x52\x77\x88\x04\xa3\x3c\xba\x8e\xf2\x5b\x31\x96\x32\xb4\x9a\x8e\xd3\xf0\x59\x9c\xfd\x2e\xc4\x68\x08\xee\x83\xde\xf3\x20\x86\xf8\x40\xee\x02\x46\x38\x93\x95\x51\x8a\xad\x5c\x40\x13\x79\x20\xf2\x60\x62\x93\x72\x42\x71\x79\x2b\x6a\x49\x98\xa5\x51\x28\xbe\x83\x79\x55\xe2\xa4\x96\x60\xad\xeb\x20\xc6\x33\x9e\x04\xa5\x41\xf6\x1b\x09\x56\xd7\xe6\x1b\x46\x2a\x80\xd8\x37\xc4\x4d\x14\xc7\x62\x1a\x5c\x93\x67\xc9\xa5\x39\xab\xfc\x36\x26\x6b\xe9\x92\xe8\xa2\x64\x9c\x1e\x89\x69\x9e\xcf\xd5\xd1\xd6\x16\xac\x5a\xc6\x29\x4c\x43\x55\x27\x69\x3a\x89\x65\x15\x9b\xdc\xba\x91\x97\x5b\x8b\x79\x08\xcb\x53\x5b\xbb\xdb\x3b\x4f\xb6\x76\x76\xb6\xbc\xc5\x7c\x9e\x66\x79\x65\x9c\x66\x95\xd2\x06\x2a\x51\x52\xa9\x4f\xb3\x14\xf7\x7b\xef\xf3\x4b\xc3\xbe\x35\x3c\x75\xba\x0e\xc4\x00\x1d\xf9\x5d\x67\x58\xf3\x87\xb5\x16\x44\x71\xf1\xee\x78\xbc\xbf\xf7\x64\xef\x82\x18\x0a\x5e\x0b\x15\x7d\xca\x52\x19\x47\x31\x29\x8a\xcd\x1e\xfb\x99\xc7\xc1\x2d\xc4\xb1\x69\xf6\xa0\xc8\x27\x0f\xbb\xd1\xc9\x63\xb6\xd5\x46\xdb\x1b\x74\x6a\x2f\x7d\x0a\x28\xbe\xd7\xfe\x88\x7c\xe2\x70\xef\xf0\xf0\x60\xfb\x90\x2d\xab\x1a\x84\xb3\x28\x59\xb7\x2f\xb2\xfd\x87\x2d\x81\x62\xc5\xba\x21\xec\x6f\xbf\x6d\xa2\x0f\x92\x70\x9d\x41\xff\x41\x12\x49\x9a\x23\x72\x3d\x4c\xa4\xd7\x1f\xb6\xeb\x77\xed\x7a\x7f\x8d\x4c\x9a\x4d\x82\x24\xfa\x54\x7b\xfb\x43\xb4\xfa\x6e\xeb\x2d\x7e\x58\x42\x24\x8e\x7b\x1c\xf0\x1b\xee\x6e\x67\x1f\xd4\x66\x41\x76\x15\xa6\x37\x2c\x6f\x27\x21\x4b\x84\x0d\x66\x21\xcc\x14\x13\x2f\x11\x93\xae\xe0\xb8\xb9\x4c\x14\x98\xb5\x9c\x5e\xed\x04\x4a\x43\x14\x6c\x20\xd2\xf4\x1c\xff\x04\x71\xe7\x59\x29\xa6\x75\x22\xc5\xa1\x6b\xb4\x50\x79\x3a\x13\x67\x6e\xa7\xe2\x8d\xc8\xe0\x4a\xbc\x21\xbc\x33\x73\x14\x7c\xa2\xe4\x4a\x89\x9b\xa9\x4c\xb0\x81\x24\x94\x59\x94\x4c\x60\x58\x9a\x23\x90\x83\x49\x62\xf5\x60\x36\x07\x57\xc8\x02\xf6\x2c\x98\x24\x88\xc5\x3a\x31\xf9\xa0\xee\x7b\x75\xb2\x54\x0f\x11\xd9\x7a\x05\xa1\x5c\x93\x5c\x06\x6e\x7f\xd8\x87\xed\x82\x2f\x72\x15\xab\xd1\xef\xd6\xda\x3d\xdc\x71\x6e\x99\xa6\x2a\xe7\xf0\x4f\xf3\xf1\xf0\xbd\xcd\x62\xfc\x63\x72\xaa\xf7\x36\xf5\x70\xdc\xbc\xb7\x79\x3a\x1c\x0e\xfc\x41\xdf\x1d\x3e\x56\x5b\x16\xdf\xd4\x1a\x0d\x4a\x49\xdb\x55\xfe\xbf\xb5\x1c\x80\x67\x7b\x14\x1a\x11\x74\x65\x36\x43\xe4\x22\xdd\x12\xfb\x8b\x24\x82\x9f\xa4\xa3\x2b\xf0\x7d\xd6\x6b\x7f\xe8\x7b\xfd\xfa\x33\x67\xe8\x0f\x1c\xb7\x8b\xe8\x85\x98\x8d\xa9\x07\x07\x07\x24\x3c\x62\x4f\x6c\x36\xba\x1f\x3d\x26\xc9\xf1\x74\x4a\x9d\xe2\x26\xcd\xae\xc8\xfe\x37\xd5\x02\xf1\x1c\x72\xf3\xbc\x53\xa1\x7d\xfc\x31\x42\x18\x4c\x52\x91\xe0\xe0\xf9\x42\xe9\xec\x5a\x05\xb9\x76\x22\x66\xd8\xab\x18\x05\x0a\xe2\Line truncated
|
||||
var _confAppIni = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xb4\x5b\x5b\x6f\x23\xc9\x75\x7e\xef\x5f\x51\xab\xcd\x66\x34\x41\x93\xd4\x65\xa4\xd1\xca\x96\xb3\x14\xd9\x94\xe8\xe1\xcd\xdd\xd4\xcc\xce\x0e\x84\x56\x8b\x5d\x24\x7b\xd5\xec\xe6\x76\x35\xa5\xd1\x22\x08\x6c\xe4\x21\x17\x20\xc8\x43\x82\x04\x01\x82\x20\x79\x48\x0c\x38\x37\x1b\x79\xb1\x13\x27\x2f\x9b\xbc\xcf\xfe\x07\x67\x1d\x3f\xf9\x2f\xe4\x3b\xa7\xaa\xc9\xa6\x46\xab\xec\xe6\xea\x15\xfb\x52\x75\xaa\xce\xfd\x3b\xa7\x7a\xde\x15\x3d\xe7\xb9\xe3\x0a\xfe\xd3\xed\x37\xdb\xad\x97\x62\x78\xda\xf6\x44\xab\xdd\x71\xac\x77\xc5\xa0\xe3\xd4\x3d\x47\x74\xeb\xcf\x1c\xd1\x38\xad\xf7\x4e\x1c\x4f\xf4\x7b\xa2\xd1\x77\x5d\xc7\x1b\xf4\x7b\xcd\x76\xef\x44\x34\xce\xbc\x61\xbf\x8b\x87\xbd\x56\xfb\x44\xcf\xb4\xbe\x21\xea\xf3\xb9\x48\x82\x99\x14\xf9\x34\xc8\x85\x9a\xa6\x37\x4a\xa4\x89\x90\xd7\x32\xbb\x15\xf3\x60\x82\x17\x51\x1e\x4b\xab\x3e\x18\xf8\xbd\x7a\xd7\x11\x47\xe2\x24\x9d\xa8\x43\xfc\x15\x27\x51\x2e\x3c\x99\x5d\x47\x23\x09\x4a\x8d\x69\x90\x60\x38\x9e\x45\x63\x71\x9b\x2e\x44\xb6\x48\x44\x9c\x8e\x82\x38\xbe\xb5\xdc\xb3\x9e\x7f\xe6\x61\xf7\x47\x62\x12\xe5\x18\xed\x44\xf9\x54\x66\x62\x23\x94\xd7\x1b\xb6\xd8\x98\x67\x69\xb8\x21\x52\x3c\xc8\xa5\xca\xf1\x24\x94\xe3\x60\x11\x83\x96\xd2\x63\x98\x02\x58\xa7\x0d\xe0\xde\xb2\x5e\x65\x72\x9e\xaa\x28\x4f\xb3\xdb\x73\xcb\xed\xf7\x87\xe2\xc8\xf2\x1a\x6e\x7b\x30\xf4\x87\x2f\x07\x34\xec\x32\x50\x53\xac\xd4\x34\x94\xea\x3d\xaf\x2d\x46\xd3\x20\x53\x32\xb7\xe8\xc6\x87\xa8\x5c\xcf\xa1\x89\xdf\x10\xad\x34\x1b\x49\xc3\x76\x22\x6f\xc4\x8a\xba\xc8\x53\x71\x29\xc5\x3c\x8b\xae\x83\x5c\x5a\xad\xbe\xdb\x70\xfc\x81\xdb\x7e\x5e\x1f\xd2\x2a\xe3\x20\x56\xc4\xfe\x49\x9c\x5e\x06\xb1\x98\x05\xaf\xa3\xd9\x62\x26\x46\x99\x0c\xf2\x08\x92\x8c\xa3\x19\x44\x92\x8e\xcb\x14\xe7\xe0\x7c\xa1\x64\x66\x8b\xca\xb6\x98\xc9\x20\x51\x22\x49\xf5\x48\xab\x5b\xff\xd0\x6f\xb8\x4e\x7d\xd8\xee\xf7\xfc\x4e\xbb\xdb\xc6\xfe\x30\x0c\x2b\x0c\x82\x7c\x34\x15\x24\x1f\xf1\xc9\x42\x2e\xa4\x88\x65\x32\xc9\xa7\x36\xd6\xbc\x62\xb9\x07\x4a\xc4\x41\x06\x1d\xe0\x02\x6b\xa9\xe8\x12\x8a\x1b\x9c\x75\x3a\xbe\xeb\x7c\xe7\xcc\xf1\x86\x3e\xfe\x9e\x39\x7e\xc7\xe9\x9d\x0c\x4f\x41\x76\x7b\x0b\xff\x07\x51\xca\x90\xf6\x75\x8e\x35\x3a\x91\xe2\xcd\x8e\xa3\x18\xd2\x78\x9d\xcb\x44\x81\x09\xb5\xb4\x8e\x45\x1c\x8a\x69\x70\x8d\xb5\xa3\x44\x8a\x9b\x2c\x98\x2b\x11\x25\x78\x2d\x45\x23\x0d\x65\x37\xca\x32\x28\x51\xd3\x03\x39\x4f\xce\x83\x0c\x52\x2b\x93\xba\x81\xe6\x45\x20\x46\xe9\x6c\x16\x54\xc5\x30\x5d\x91\xe2\x55\x31\xa0\x96\xae\xc6\xdb\xe2\xe3\x05\xb6\x34\x5f\xe4\xc5\x1c\xab\xd3\xee\x39\xfe\x0b\xb7\x3e\xf0\x9d\x0f\x87\x0e\x14\xd9\xef\x79\x60\xa6\x9a\xbf\xce\xed\xea\x2c\xc4\x7f\x41\x76\x15\xa6\x37\x09\xdd\xe9\x9f\xab\xd0\xc6\x6e\x9e\x07\x71\x14\x6a\xd6\x66\xd8\xac\xe1\x8a\xd9\x09\xa0\x5f\x79\x1d\x41\xf1\xf5\x41\x1b\xf2\x53\xe9\x28\xc2\xbe\x43\xbd\x5b\xb0\x37\xb3\x85\x5a\x40\xfc\x10\x6d\x30\x8f\x6a\xd7\xdb\xb5\x62\x95\x32\x9b\xd7\x41\xbc\x00\xdd\xcb\x5b\xbd\x55\x55\x15\x03\x43\x36\x0f\x2e\x49\x50\x24\x19\x5e\x5c\xdc\xa4\xc9\x23\xed\x70\xe4\x2f\x24\xc0\x75\x99\x8b\x30\x95\x8a\x86\xcc\x48\xed\xd6\xc0\x75\x9e\xb7\x9d\x17\xfe\xb0\x7e\xec\x63\x8b\xc4\xf0\x72\x03\xd6\xab\xc5\x3c\x4e\x83\x90\x14\xf8\x62\x2a\xd9\xb1\x4a\xd6\xc6\x74\xf5\x08\x6c\x3e\xc3\x1a\x49\x00\xcb\x08\xab\x85\x6b\x28\x32\xf1\x8b\x3c\x5b\xc8\x0b\xcb\xe9\xd5\x8f\x3b\x8e\x7f\x36\xe8\xf4\xeb\x4d\x5a\x85\x1e\x6b\xe3\x9b\x8a\x31\x74\x6b\x08\xdd\x99\x1c\x06\x79\x50\xcb\x67\xf3\x9a\x79\x7d\x21\x36\x71\x27\x26\x12\xef\x43\x19\x4b\x12\x25\x78\x9a\x20\x74\x60\x6b\x2a\x0f\xb2\xfc\xb1\x35\x74\xba\x03\x7f\x50\x67\x53\xbc\x4b\x00\x4b\xf6\x61\x16\x58\x70\x96\x62\xcb\x08\x22\xe9\x0d\x68\xe4\xb7\x73\xa9\x6c\x21\xab\x93\xaa\x88\x66\x08\x4f\xb5\x8f\xe7\x72\xf2\x1b\xfa\x72\x9e\xe0\x69\x2f\xcd\xa7\x51\x32\x31\x6e\x15\x24\x86\x7f\x9a\x68\xd5\x3b\x9d\xfe\x0b\xa7\xc9\x01\xc2\x63\xb7\xef\x06\xaf\x85\x8a\x3e\x95\x64\xf3\x32\x80\x7e\x79\x30\x14\xd5\x3d\x5e\xe7\x70\x77\xa7\x7b\x6c\x51\xd0\xf4\xc9\x41\xbd\xf6\x47\xe4\xfb\xbb\x3b\x86\x44\xb2\x98\x5d\x42\xe8\xc6\x71\x94\x76\x70\x66\x64\x9d\xca\xf6\x16\xfb\x37\xd1\xf1\xd8\xff\x48\x77\x11\xe9\xad\xb7\xa4\xb0\xd4\x5c\x54\x58\x28\xe9\x8c\x0c\x05\xfc\x63\x67\x69\x42\x56\x02\xe2\x78\x4a\x01\xda\x72\x3e\x84\xb2\x5c\xc4\xa4\xfa\x09\xe2\xbc\xdf\x3b\xeb\x82\xf4\xce\xd6\x1a\xd1\x48\xa9\xc5\x97\x93\x63\x32\x6d\xcf\x3b\xbb\x43\x64\x7b\x9d\xc8\x32\xb6\xc1\xb6\x23\x30\xb4\x4e\x24\x18\xe5\xd1\x75\x94\x43\xde\x52\x86\x56\xcb\x81\x9c\x39\x96\xf5\xbb\x88\x61\x86\xe0\x9e\xf6\xc2\x05\xcb\xfb\x82\xdc\x4a\x56\x46\x29\x58\xb9\x80\xbe\xf2\x00\x5e\x32\xb1\x29\x32\x86\xe4\x42\xf5\x24\xcc\x52\x38\xec\xb7\x30\xaf\x4a\x3b\xa9\x27\x58\xeb\x9a\x9d\x98\x27\x21\x72\x20\xf0\x6d\x24\x58\x5d\xe7\x8e\x30\x52\x64\xd9\x1b\xf0\xda\x38\xd6\x8e\x4d\x8e\x55\xe4\x12\x95\xdf\xc6\x64\xcb\x5d\x12\x5d\x94\x8c\xd3\x43\x31\xcd\xf3\xb9\x3a\xac\xd5\x90\x52\x64\x9c\x42\x6d\xaa\x3a\x49\xd3\x49\x2c\xab\x60\xb2\x76\x23\x2f\x61\x8f\x30\x4d\xa9\x6a\x3b\x5b\xdb\x4f\x6a\xdb\xdb\x35\x6f\x31\x9f\xa7\x59\x5e\x81\x2f\x54\x4a\x0c\x54\xa2\xa4\xd2\x98\x66\x29\xee\x77\xdf\xe7\x97\x66\xfb\xd6\xf0\Line truncated
|
||||
|
||||
func confAppIniBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
@@ -301,7 +301,7 @@ func confAppIni() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "conf/app.ini", size: 12337, mode: os.FileMode(420), modTime: time.Unix(1470994320, 0)}
|
||||
info := bindataFileInfo{name: "conf/app.ini", size: 13442, mode: os.FileMode(420), modTime: time.Unix(1471215870, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -4346,7 +4346,7 @@ func confLocaleLocale_deDeIni() (*asset, error) {
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _confLocaleLocale_enUsIni = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xac\xbd\xfb\x72\xdc\x46\x92\x2f\xfc\x3f\x9e\x02\xd6\x84\x42\x52\x04\xd5\x0e\x8f\xf7\xbb\x84\xc3\x97\x8f\xa2\xac\xcb\xae\x28\x71\x45\xda\xf3\xcd\x71\x28\xda\x60\x37\xd8\x8d\x55\x37\xd0\x03\xa0\x49\x71\x26\xe6\x0d\xce\x03\x9c\xe7\x3b\x4f\x72\x32\x7f\x99\x59\x95\x05\xa0\x49\xc9\xb3\xfa\x43\x44\x57\x65\xdd\xb3\xb2\xf2\x56\x59\xc5\x6e\x37\x5f\x96\xdd\x22\xff\x21\x3f\xce\x77\x45\x55\x6f\xca\xae\xcb\xbb\x72\x73\xf5\x74\xdd\x74\x7d\xb9\xcc\x5f\x56\x3d\xfd\x6e\xaf\xab\x45\x99\x65\xeb\x66\x5b\x12\xe8\x2b\xfa\x93\x2d\x8b\x6e\x7d\xd9\x14\xed\x92\x12\x9e\xdb\x77\x56\x7e\xda\x6d\x9a\x96\x81\x7e\x96\xaf\x6c\x5d\x6e\x76\x5c\x86\xfe\x64\x5d\xb5\xaa\xe7\x55\x4d\x3f\xcf\xe9\x2b\x7f\x5d\x4b\x4a\xb3\xef\x2d\xe9\xdd\xbe\x97\xb4\xfd\xce\x92\x7e\xd9\x65\x6d\xb9\xaa\xa8\x37\x2d\x25\xbd\xd7\xcf\xec\xa6\xbc\xec\xaa\x9e\x5b\xfa\x8b\x7c\x65\xd7\x65\xdb\x55\x0d\xd7\xfe\xab\x7c\x65\xbb\x62\xc5\x00\x67\xf4\x27\xeb\xcb\xed\x6e\x53\xa0\xc0\x85\x7e\x66\x9b\xa2\x5e\xed\x05\xe6\x8d\x7e\x66\x8b\xb6\xa4\xac\x79\x5d\xde\x50\xea\x09\x7e\xcc\x66\xb3\x6c\x4f\x93\x30\xdf\xb5\xcd\x55\xb5\x29\xe7\x45\xbd\x9c\x6f\x65\x98\xbf\x50\x7a\xae\xe9\x39\xa5\xe7\x9c\x8e\x21\x94\x4b\x1a\xea\xbc\xe8\x74\x1c\x34\x97\x34\xf2\xa2\xcb\x50\x55\x5d\x6c\xad\x34\x7f\x66\xe5\xb6\xa8\x36\x3c\x6b\xfc\x97\xfa\xdd\x75\x37\x0d\xa6\xf6\x4c\x3f\x69\x0e\xe6\xfd\xed\xae\xc4\x14\x3c\xbd\xa0\xaf\x6c\x51\xec\xfa\xc5\xba\xe0\x6e\xca\x57\x46\x40\xbb\x86\xe6\xa2\x69\x6f\x01\x67\x3f\xb2\xa6\x5d\x15\x75\xf5\xf7\xa2\x97\xf9\x79\xe7\x7e\x66\xdb\xaa\x6d\x1b\x9e\xda\x53\x7c\x64\x34\xf2\x39\xd7\x43\x29\x6f\x69\x12\x5c\x2d\x9c\xb3\xad\x56\xad\xcc\x22\x67\x9e\xe2\x17\xd7\x22\x79\x5a\x93\x64\x85\xda\xae\x9a\xf6\xa3\xa6\xbe\xe0\xcf\x41\x95\xd4\x39\xcd\x4d\xfb\x55\xd4\xb4\x1e\x9a\x7b\x8a\x1f\x09\x40\x97\x15\xcb\x2d\xcd\xf0\xae\xa8\x4b\x9e\xba\x63\xfe\x45\xf3\x45\xbf\xb2\x62\xb1\x68\xf6\x75\x3f\xef\xca\xbe\xaf\xea\x15\xaf\xc1\xb1\x24\xe5\xe7\x9a\x94\xb9\xbc\x90\x76\xdb\xec\xc3\x2a\x53\xfa\x5f\xe9\x67\x7e\x26\x3f\x25\xcf\x15\x42\x66\x28\x49\x4d\xf6\xd5\x75\xd5\x57\xa5\x34\x66\x3f\xb2\xdd\x7e\xb3\xa1\xf9\xfc\xdb\xbe\xec\x7a\xce\x3a\xa3\xdf\x34\x03\xf2\x3b\xab\xba\x6e\x8f\x12\xaf\xf1\x91\xd1\xa2\xd6\x0b\x0c\xe7\x04\x1f\x59\xf6\x5b\x55\x77\x7d\xb1\xd9\x7c\xc8\xf4\x83\x81\xe5\x4b\xe6\xa9\xaf\x7a\x74\x56\x13\xf3\xf3\xbe\xdc\x75\x3c\xd1\xf9\x8b\xaa\xed\xfa\xa7\x7d\x45\xa8\xf6\x7e\x5f\x67\xcb\x66\xf1\x91\x90\x98\x37\x24\xb6\xd2\xeb\xab\x9c\xc6\xf4\x88\xd0\xb8\xdd\xd7\x35\x8d\x22\x7f\xd9\xd0\xc8\xa8\x99\x6a\x59\xe6\xcf\x01\x7d\x94\xef\x36\x65\xd1\x11\x48\x59\x2c\xf3\xef\x8b\xbc\x2f\xda\x55\xd9\xff\xf0\x60\x7e\x49\x9b\xe7\xe3\x83\x7c\xdd\x96\x57\x3f\x3c\x78\xd8\x3d\xf8\xf1\xe5\x9e\x8a\x6d\xaa\xba\xec\xbe\xff\xba\xf8\x31\x5f\x14\x94\x43\x63\xbd\xcd\x2f\xcb\x2b\xde\x2b\xd4\x56\x4e\x48\x5a\xaf\x78\x9f\xdc\xf6\x6b\x6e\x90\x16\x8c\x3e\xba\x9c\x37\xea\x57\x19\xcf\x12\x6d\xe4\xf9\xf2\xd2\x88\x12\x3a\x84\xe4\x96\x66\xe9\xf4\xf6\xfc\x3f\xdf\x1c\xe5\x67\x44\x99\x56\x6d\x89\x6f\xfa\x8f\x4a\x7c\x9b\xd3\x68\x2f\xaa\xe7\xcf\x66\x19\x95\xb5\x09\x79\x5e\xf4\xc5\x25\xf7\x3d\x2c\x12\x67\xca\x1e\x0a\x79\xd8\x49\x4c\xeb\x40\xd7\xba\x1e\xbb\x53\x77\xe6\xe4\x3e\xa4\x3a\x74\xf3\x86\x3a\xde\xf2\x0e\xa6\xf4\x30\xb3\x67\x32\x67\x54\x55\xfe\xfa\xed\xdb\x77\xcf\x9f\xe5\x65\xbd\xa2\x99\xc9\x6f\xaa\x7e\x9d\xef\xfb\xab\xff\x77\xbe\x2a\xeb\xb2\x2d\x36\xf3\x45\xc5\x93\xd2\x12\x5e\xe5\x34\x4b\x32\xc4\x59\xd6\x75\x1b\x22\x30\x4b\x6e\xe5\xfc\xfc\x4d\x7e\x4a\x9f\xd4\x19\x2a\xcb\x1d\xe9\xd7\x59\xf7\xb7\x0d\x4f\x54\x68\xf0\x62\x5d\xe6\xc0\x59\x00\x35\x57\xc3\x79\xc9\x97\xda\xd7\x59\xfe\xfd\x65\xfb\xa3\xeb\x5f\x71\xd9\x35\x9b\x7d\xaf\x25\x6f\xd6\x65\x8d\x85\x22\x54\x6a\x7b\xa2\x56\x46\xfb\x67\x59\xd9\xb6\x73\xa2\x9b\xfd\x2d\x2f\x8f\xf6\xe5\x50\x2b\x52\x19\xa1\x72\xdd\xf4\xb4\xfc\x39\xca\x49\x15\x55\x7d\x5d\x6c\xaa\x25\x2d\x52\x9c\xc8\xb4\x2c\x12\x97\x0d\xad\x37\x97\x26\x8c\x6e\x6e\x30\x45\xb4\xc1\x88\xac\xe7\x0f\x66\x0f\x40\x67\x1f\x3c\x7d\x30\xcb\xea\x66\x2e\x44\x80\x29\xf2\xb2\xea\x8a\x4b\xa2\xce\x72\x5a\xb4\x46\xec\xfe\xca\x78\x27\x5d\x51\x88\x3c\x81\xe0\x35\xe1\x13\x08\x84\x9f\x91\xb2\x20\x32\x0d\x5a\xa2\x54\xc4\x8f\xdd\x48\x4e\xc0\x0b\xa1\x3a\x21\x61\x34\xe6\xcc\x16\xda\xb0\xf2\x78\xb7\xdb\x54\x0b\x69\xfa\xa5\xe4\x45\x04\xe5\xf3\x58\x27\xc5\xc3\x01\xc1\x2c\xcf\xa1\x19\xf5\x9a\xa9\x52\x9e\x90\x77\x94\x5f\x97\xb4\xe3\xd6\xfb\x95\x9c\x49\x9b\x66\xbf\xfc\x0a\x87\x83\xad\x5c\x24\xc1\xf9\xfb\x86\x3a\x0c\xac\x0a\x00\xb1\x89\x63\x22\x28\xcc\x02\xb4\xe5\xb6\xe9\x79\xe2\xb4\x18\x93\xb9\x9b\x8a\x32\x69\xa4\x5d\x71\x4d\x87\x5b\xdf\xc8\x56\x5e\xd2\x56\x5d\x70\xc5\xb3\x8c\xc8\xca\x5c\xb7\x13\xd1\x1f\xd9\x52\x96\x96\xe2\x2e\xa0\xb6\x7b\xda\x85\x6b\xaa\x8c\x27\x9e\xf9\x10\xaa\x72\xaa\x9f\x18\x12\xd5\x03\xea\x40\x3b\xbe\xa1\x33\x93\x17\xfa\x39\x3e\xf4\xb7\xaf\x9f\x7a\x55\x5c\x5d\x51\xaf\x3a\xda\x4d\xaf\xf2\xc5\xa6\xa1\xad\xf8\xcb\xfb\x37\x1d\x6f\xb4\xf5\x7c\xd7\xb4\xe0\x3f\x28\xeb\x8c\x3e\x43\x9a\x9b\x68\x86\xa8\xf7\xdb\x4b\xfa\x75\xb3\xae\x16\x6b\x99\x76\x2e\xc1\xfb\x83\x52\xa9\x8Line truncated
|
||||
var _confLocaleLocale_enUsIni = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xac\xbd\xfb\x72\xdb\x48\x92\x2f\xfc\x3f\x9e\x02\xed\x09\x87\xed\x08\x99\x1d\x3d\xb3\xdf\x25\x3a\xfa\xf2\xa9\xe5\xf6\x65\xd7\xb2\xb5\x96\x7a\xe6\x9b\xd3\xe1\x60\x83\x24\x44\x62\x4d\x02\x1c\x00\xb4\xac\x99\x98\x37\x38\x0f\x70\x9e\xef\x3c\xc9\xc9\xfc\x65\x66\x55\x16\x00\x4a\x76\xcf\xfa\x0f\x0b\xac\xca\xba\x67\x65\xe5\xad\xb2\x8a\xfd\x7e\xbe\x2a\xbb\x65\xfe\x7d\x7e\x9a\xef\x8b\xaa\xde\x96\x5d\x97\x77\xe5\xf6\xfa\xe9\xa6\xe9\xfa\x72\x95\xbf\xa8\x7a\xfa\xdd\x7e\xac\x96\x65\x96\x6d\x9a\x5d\x49\xa0\x2f\xe9\x4f\xb6\x2a\xba\xcd\xa2\x29\xda\x15\x25\x3c\xb3\xef\xac\xfc\xb4\xdf\x36\x2d\x03\xfd\x2c\x5f\xd9\xa6\xdc\xee\xb9\x0c\xfd\xc9\xba\x6a\x5d\xcf\xab\x9a\x7e\x5e\xd2\x57\xfe\xaa\x96\x94\xe6\xd0\x5b\xd2\xdb\x43\x2f\x69\x87\xbd\x25\xfd\xb2\xcf\xda\x72\x5d\x51\x6f\x5a\x4a\x7a\xa7\x9f\xd9\x4d\xb9\xe8\xaa\x9e\x5b\xfa\x8b\x7c\x65\x1f\xcb\xb6\xab\x1a\xae\xfd\xcf\xf2\x95\xed\x8b\x35\x03\x5c\xd0\x9f\xac\x2f\x77\xfb\x6d\x81\x02\x57\xfa\x99\x6d\x8b\x7a\x7d\x10\x98\xd7\xfa\x99\x2d\xdb\x92\xb2\xe6\x75\x79\x43\xa9\x67\xf8\x31\x9b\xcd\xb2\x03\x4d\xc2\x7c\xdf\x36\xd7\xd5\xb6\x9c\x17\xf5\x6a\xbe\x93\x61\xfe\x42\xe9\xb9\xa6\xe7\x94\x9e\x73\x3a\x86\x50\xae\x68\xa8\xf3\xa2\xd3\x71\xd0\x5c\xd2\xc8\x8b\x2e\x43\x55\x75\xb1\xb3\xd2\xfc\x99\x95\xbb\xa2\xda\xf2\xac\xf1\x5f\xea\x77\xd7\xdd\x34\x98\xda\x0b\xfd\xa4\x39\x98\xf7\xb7\xfb\x12\x53\xf0\xf4\x8a\xbe\xb2\x65\xb1\xef\x97\x9b\x82\xbb\x29\x5f\x19\x01\xed\x1b\x9a\x8b\xa6\xbd\x05\x9c\xfd\xc8\x9a\x76\x5d\xd4\xd5\xdf\x8b\x5e\xe6\xe7\xad\xfb\x99\xed\xaa\xb6\x6d\x78\x6a\xcf\xf1\x91\xd1\xc8\xe7\x5c\x0f\xa5\xbc\xa1\x49\x70\xb5\x70\xce\xae\x5a\xb7\x32\x8b\x9c\x79\x8e\x5f\x5c\x8b\xe4\x69\x4d\x92\x15\x6a\xbb\x6e\xda\x0f\x9a\xfa\x9c\x3f\x07\x55\x52\xe7\x34\x37\xed\x57\x51\xd3\x7a\x68\xee\x39\x7e\x24\x00\x5d\x56\xac\x76\x34\xc3\xfb\xa2\x2e\x79\xea\x4e\xf9\x17\xcd\x17\xfd\xca\x8a\xe5\xb2\x39\xd4\xfd\xbc\x2b\xfb\xbe\xaa\xd7\xbc\x06\xa7\x92\x94\x5f\x6a\x52\xe6\xf2\x42\xda\x6d\x73\x08\xab\x4c\xe9\x7f\xa5\x9f\xf9\x85\xfc\x94\x3c\x57\x08\x99\xa1\x24\x35\xd9\x57\x1f\xab\xbe\x2a\xa5\x31\xfb\x91\xed\x0f\xdb\x2d\xcd\xe7\xdf\x0e\x65\xd7\x73\xd6\x05\xfd\xa6\x19\x90\xdf\x59\xd5\x75\x07\x94\x78\x85\x8f\x8c\x16\xb5\x5e\x62\x38\x67\xf8\xc8\xb2\x5f\xab\xba\xeb\x8b\xed\xf6\x7d\xa6\x1f\x0c\x2c\x5f\x32\x4f\x7d\xd5\xa3\xb3\x9a\x98\x5f\xf6\xe5\xbe\xe3\x89\xce\x9f\x57\x6d\xd7\x3f\xed\x2b\x42\xb5\x77\x87\x3a\x5b\x35\xcb\x0f\x84\xc4\xbc\x21\xb1\x95\x5e\x5d\xe7\x34\xa6\x47\x84\xc6\xed\xa1\xae\x69\x14\xf9\x8b\x86\x46\x46\xcd\x54\xab\x32\x7f\x06\xe8\x93\x7c\xbf\x2d\x8b\x8e\x40\xca\x62\x95\x7f\x57\xe4\x7d\xd1\xae\xcb\xfe\xfb\x07\xf3\x05\x6d\x9e\x0f\x0f\xf2\x4d\x5b\x5e\x7f\xff\xe0\x61\xf7\xe0\x87\x17\x07\x2a\xb6\xad\xea\xb2\xfb\xee\xeb\xe2\x87\x7c\x59\x50\x0e\x8d\xf5\x36\x5f\x94\xd7\xbc\x57\xa8\xad\x9c\x90\xb4\x5e\xf3\x3e\xb9\xed\x37\xdc\x20\x2d\x18\x7d\x74\x39\x6f\xd4\xaf\x32\x9e\x25\xda\xc8\xf3\xd5\xc2\x88\x12\x3a\x84\xe4\x96\x66\xe9\xfc\xf6\xf2\x3f\x5f\x9f\xe4\x17\x44\x99\xd6\x6d\x89\x6f\xfa\x8f\x4a\xfc\x29\xa7\xd1\x5e\x55\xcf\x7e\x9a\x65\x54\xd6\x26\xe4\x59\xd1\x17\x0b\xee\x7b\x58\x24\xce\x94\x3d\x14\xf2\xb0\x93\x98\xd6\x81\xae\x75\x3d\x76\xa7\xee\xcc\xc9\x7d\x48\x75\xe8\xe6\x0d\x75\xbc\xe1\x1d\x4c\xe9\x61\x66\x2f\x64\xce\xa8\xaa\xfc\xd5\x9b\x37\x6f\x9f\xfd\x94\x97\xf5\x9a\x66\x26\xbf\xa9\xfa\x4d\x7e\xe8\xaf\xff\xdf\xf9\xba\xac\xcb\xb6\xd8\xce\x97\x15\x4f\x4a\x4b\x78\x95\xd3\x2c\xc9\x10\x67\x59\xd7\x6d\x89\xc0\xac\xb8\x95\xcb\xcb\xd7\xf9\x39\x7d\x52\x67\xa8\x2c\x77\xa4\xdf\x64\xdd\xdf\xb6\x3c\x51\xa1\xc1\xab\x4d\x99\x03\x67\x01\xd4\x5c\x0f\xe7\x25\x5f\x69\x5f\x67\xf9\x77\x8b\xf6\x07\xd7\xbf\x62\xd1\x35\xdb\x43\xaf\x25\x6f\x36\x65\x8d\x85\x22\x54\x6a\x7b\xa2\x56\x46\xfb\x67\x59\xd9\xb6\x73\xa2\x9b\xfd\x2d\x2f\x8f\xf6\xe5\x58\x2b\x52\x19\xa1\x72\xdd\xf4\xb4\xfc\x39\xca\x49\x15\x55\xfd\xb1\xd8\x56\x2b\x5a\xa4\x38\x91\x69\x59\x24\xae\x1a\x5a\x6f\x2e\x4d\x18\xdd\xdc\x60\x8a\x68\x83\x11\x59\xcf\x1f\xcc\x1e\x80\xce\x3e\x78\xfa\x60\x96\xd5\xcd\x5c\x88\x00\x53\xe4\x55\xd5\x15\x0b\xa2\xce\x72\x5a\xb4\x46\xec\xfe\xca\x78\x27\x5d\x51\x88\x3c\x81\xe0\x35\xe1\x13\x08\x84\x9f\x91\xb2\x20\x32\x0d\x5a\xa2\x54\xc4\x8f\xdd\x48\x4e\xc0\x0b\xa1\x3a\x21\x61\x34\xe6\xcc\x16\xda\xb0\xf2\x74\xbf\xdf\x56\x4b\x69\xfa\x85\xe4\x45\x04\xe5\xf3\x58\x27\xc5\xc3\x01\xc1\x2c\xcf\xa1\x19\xf5\x9a\xa9\x52\x9e\x90\x77\x94\xdf\x94\xb4\xe3\x36\x87\xb5\x9c\x49\xdb\xe6\xb0\xfa\x0a\x87\x83\xad\x5c\x24\xc1\xf9\xbb\x86\x3a\x0c\xac\x0a\x00\xb1\x89\x53\x22\x28\xcc\x02\xb4\xe5\xae\xe9\x79\xe2\xb4\x18\x93\xb9\x9b\x8a\x32\x69\xa4\x5d\xf1\x91\x0e\xb7\xbe\x91\xad\xbc\xa2\xad\xba\xe4\x8a\x67\x19\x91\x95\xb9\x6e\x27\xa2\x3f\xb2\xa5\x2c\x2d\xc5\x5d\x40\xed\x0e\xb4\x0b\x37\x54\x19\x4f\x3c\xf3\x21\x54\xe5\x54\x3f\x31\x24\xaa\x07\xd4\x81\x76\x7c\x43\x67\x26\x2f\xf4\x33\x7c\xe8\x6f\x5f\x3f\xf5\xaa\xb8\xbe\xa6\x5e\x75\xb4\x9b\x5e\xe6\xcb\x6d\x43\x5b\xf1\x97\x77\xaf\x3b\xde\x68\x9b\xf9\xbe\x69\xc1\x7f\x50\xd6\x05\x7d\x86\x34\x37\xd1\x0c\x51\x1f\x76\x0b\xfa\x75\xb3\xa9\x96\x1b\x99\x76\x2e\xc1\xfb\x83\x52\xa9\x8Line truncated
|
||||
|
||||
func confLocaleLocale_enUsIniBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
@@ -4361,7 +4361,7 @@ func confLocaleLocale_enUsIni() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "conf/locale/locale_en-US.ini", size: 52773, mode: os.FileMode(420), modTime: time.Unix(1471166949, 0)}
|
||||
info := bindataFileInfo{name: "conf/locale/locale_en-US.ini", size: 55126, mode: os.FileMode(420), modTime: time.Unix(1471215870, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
@@ -53,10 +53,11 @@ func isLink(link []byte) bool {
|
||||
// IsMarkdownFile reports whether name looks like a Markdown file
|
||||
// based on its extension.
|
||||
func IsMarkdownFile(name string) bool {
|
||||
name = strings.ToLower(name)
|
||||
switch filepath.Ext(name) {
|
||||
case ".md", ".markdown", ".mdown", ".mkd":
|
||||
return true
|
||||
extension := strings.ToLower(filepath.Ext(name))
|
||||
for _, ext := range setting.Markdown.MdFileExtensions {
|
||||
if strings.ToLower(ext) == extension {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -118,6 +118,12 @@ var (
|
||||
RepoRootPath string
|
||||
ScriptType string
|
||||
|
||||
// Repo editor settings
|
||||
Editor struct {
|
||||
LineWrapExtensions []string
|
||||
PreviewTabApis []string
|
||||
}
|
||||
|
||||
// UI settings
|
||||
UI struct {
|
||||
ExplorePagingNum int
|
||||
@@ -141,6 +147,7 @@ var (
|
||||
Markdown struct {
|
||||
EnableHardLineBreak bool
|
||||
CustomURLSchemes []string `ini:"CUSTOM_URL_SCHEMES"`
|
||||
MdFileExtensions []string
|
||||
}
|
||||
|
||||
// Picture settings
|
||||
@@ -162,6 +169,13 @@ var (
|
||||
AttachmentMaxFiles int
|
||||
AttachmentEnabled bool
|
||||
|
||||
// Repo Upload settings
|
||||
UploadTempPath string
|
||||
UploadAllowedTypes string
|
||||
UploadMaxSize int64
|
||||
UploadMaxFiles int
|
||||
UploadEnabled bool
|
||||
|
||||
// Time settings
|
||||
TimeFormat string
|
||||
|
||||
@@ -482,6 +496,16 @@ func NewContext() {
|
||||
log.Fatal(4, "Fail to map Repository settings: %v", err)
|
||||
}
|
||||
|
||||
sec = Cfg.Section("upload")
|
||||
UploadTempPath = sec.Key("UPLOAD_TEMP_PATH").MustString(path.Join(AppDataPath, "tmp/uploads"))
|
||||
if !filepath.IsAbs(UploadTempPath) {
|
||||
UploadTempPath = path.Join(workDir, UploadTempPath)
|
||||
}
|
||||
UploadAllowedTypes = strings.Replace(sec.Key("UPLOAD_ALLOWED_TYPES").MustString(""), "|", ",", -1)
|
||||
UploadMaxSize = sec.Key("UPLOAD_FILE_MAX_SIZE").MustInt64(32)
|
||||
UploadMaxFiles = sec.Key("UPLOAD_MAX_FILES").MustInt(10)
|
||||
UploadEnabled = sec.Key("ENABLE_UPLOADS").MustBool(true)
|
||||
|
||||
sec = Cfg.Section("picture")
|
||||
AvatarUploadPath = sec.Key("AVATAR_UPLOAD_PATH").MustString(path.Join(AppDataPath, "avatars"))
|
||||
forcePathSeparator(AvatarUploadPath)
|
||||
@@ -532,6 +556,8 @@ func NewContext() {
|
||||
log.Fatal(4, "Fail to map API settings: %v", err)
|
||||
} else if err = Cfg.Section("api").MapTo(&API); err != nil {
|
||||
log.Fatal(4, "Fail to map API settings: %v", err)
|
||||
} else if err = Cfg.Section("editor").MapTo(&Editor); err != nil {
|
||||
log.Fatal(4, "Fail to map Editor settings: %v", err)
|
||||
}
|
||||
|
||||
if Mirror.DefaultInterval <= 0 {
|
||||
@@ -546,6 +572,10 @@ func NewContext() {
|
||||
ShowFooterVersion = Cfg.Section("other").Key("SHOW_FOOTER_VERSION").MustBool()
|
||||
|
||||
HasRobotsTxt = com.IsFile(path.Join(CustomPath, "robots.txt"))
|
||||
|
||||
Markdown.MdFileExtensions = Cfg.Section("markdown").Key("MD_FILE_EXTENSIONS").Strings(",")
|
||||
Editor.LineWrapExtensions = Cfg.Section("editor").Key("LINE_WRAP_EXTENSIONS").Strings(",")
|
||||
Editor.PreviewTabApis = Cfg.Section("editor").Key("PREVIEW_TAB_APIS").Strings(",")
|
||||
}
|
||||
|
||||
var Service struct {
|
||||
|
||||
+224
-27
@@ -255,6 +255,9 @@ code.wrap {
|
||||
.ui.status.buttons .octicon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
.ui.menu .item .octicon {
|
||||
margin-right: 4px;
|
||||
}
|
||||
.ui.inline.delete-button {
|
||||
padding: 8px 15px;
|
||||
font-weight: normal;
|
||||
@@ -1266,57 +1269,57 @@ footer .ui.language .menu {
|
||||
.repository.file.list #file-content .view-raw img {
|
||||
padding: 5px 5px 0 5px;
|
||||
}
|
||||
.repository.file.list #file-content .code-view * {
|
||||
#file-content .code-view * {
|
||||
font-size: 12px;
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
line-height: 20px;
|
||||
}
|
||||
.repository.file.list #file-content .code-view table {
|
||||
#file-content .code-view table {
|
||||
width: 100%;
|
||||
}
|
||||
.repository.file.list #file-content .code-view .lines-num {
|
||||
#file-content .code-view .lines-num {
|
||||
vertical-align: top;
|
||||
text-align: right;
|
||||
color: #999;
|
||||
background: #f5f5f5;
|
||||
width: 1%;
|
||||
}
|
||||
.repository.file.list #file-content .code-view .lines-num span {
|
||||
#file-content .code-view .lines-num span {
|
||||
line-height: 20px;
|
||||
padding: 0 10px;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
}
|
||||
.repository.file.list #file-content .code-view .lines-num,
|
||||
.repository.file.list #file-content .code-view .lines-code {
|
||||
#file-content .code-view .lines-num,
|
||||
#file-content .code-view .lines-code {
|
||||
padding: 0;
|
||||
}
|
||||
.repository.file.list #file-content .code-view .lines-num pre,
|
||||
.repository.file.list #file-content .code-view .lines-code pre,
|
||||
.repository.file.list #file-content .code-view .lines-num ol,
|
||||
.repository.file.list #file-content .code-view .lines-code ol,
|
||||
.repository.file.list #file-content .code-view .lines-num .hljs,
|
||||
.repository.file.list #file-content .code-view .lines-code .hljs {
|
||||
#file-content .code-view .lines-num pre,
|
||||
#file-content .code-view .lines-code pre,
|
||||
#file-content .code-view .lines-num ol,
|
||||
#file-content .code-view .lines-code ol,
|
||||
#file-content .code-view .lines-num .hljs,
|
||||
#file-content .code-view .lines-code .hljs {
|
||||
background-color: white;
|
||||
margin: 0;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.repository.file.list #file-content .code-view .lines-num pre li,
|
||||
.repository.file.list #file-content .code-view .lines-code pre li,
|
||||
.repository.file.list #file-content .code-view .lines-num ol li,
|
||||
.repository.file.list #file-content .code-view .lines-code ol li,
|
||||
.repository.file.list #file-content .code-view .lines-num .hljs li,
|
||||
.repository.file.list #file-content .code-view .lines-code .hljs li {
|
||||
#file-content .code-view .lines-num pre li,
|
||||
#file-content .code-view .lines-code pre li,
|
||||
#file-content .code-view .lines-num ol li,
|
||||
#file-content .code-view .lines-code ol li,
|
||||
#file-content .code-view .lines-num .hljs li,
|
||||
#file-content .code-view .lines-code .hljs li {
|
||||
padding-left: 5px;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
.repository.file.list #file-content .code-view .lines-num pre li.active,
|
||||
.repository.file.list #file-content .code-view .lines-code pre li.active,
|
||||
.repository.file.list #file-content .code-view .lines-num ol li.active,
|
||||
.repository.file.list #file-content .code-view .lines-code ol li.active,
|
||||
.repository.file.list #file-content .code-view .lines-num .hljs li.active,
|
||||
.repository.file.list #file-content .code-view .lines-code .hljs li.active {
|
||||
#file-content .code-view .lines-num pre li.active,
|
||||
#file-content .code-view .lines-code pre li.active,
|
||||
#file-content .code-view .lines-num ol li.active,
|
||||
#file-content .code-view .lines-code ol li.active,
|
||||
#file-content .code-view .lines-num .hljs li.active,
|
||||
#file-content .code-view .lines-code .hljs li.active {
|
||||
background: #ffffdd;
|
||||
}
|
||||
.repository.file.list .sidebar {
|
||||
@@ -1895,7 +1898,7 @@ footer .ui.language .menu {
|
||||
max-width: 100%;
|
||||
padding: 5px 5px 0 5px;
|
||||
}
|
||||
.repository .code-view {
|
||||
#file-content .code-view {
|
||||
overflow: auto;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
@@ -2157,13 +2160,13 @@ footer .ui.language .menu {
|
||||
.page.buttons {
|
||||
padding-top: 15px;
|
||||
}
|
||||
.ui.comments .dropzone {
|
||||
.ui.comments .dropzone, .ui.upload .dropzone {
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
border: 2px dashed #0087F7;
|
||||
box-shadow: none!important;
|
||||
}
|
||||
.ui.comments .dropzone .dz-error-message {
|
||||
.ui.comments .dropzone .dz-error-message, .ui.upload .dropzone .dz-error-message {
|
||||
top: 140px;
|
||||
}
|
||||
.settings .content {
|
||||
@@ -2797,3 +2800,197 @@ footer .ui.language .menu {
|
||||
.ui.user.list .item .description a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.btn-octicon {
|
||||
display: inline-block;
|
||||
padding: 5px;
|
||||
margin-left: 5px;
|
||||
line-height: 1;
|
||||
color: #767676;
|
||||
vertical-align: middle;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
outline: none;
|
||||
}
|
||||
.btn-octicon:hover {
|
||||
color: #4078c0;
|
||||
}
|
||||
.btn-octicon-danger:hover {
|
||||
color: #bd2c00;
|
||||
}
|
||||
.btn-octicon.disabled {
|
||||
color: #bbb;
|
||||
cursor: default;
|
||||
}
|
||||
.inline-form {
|
||||
display: inline-block;
|
||||
}
|
||||
.ui.form .breadcrumb input {
|
||||
min-height: 34px;
|
||||
padding: 7px 8px;
|
||||
color: #333;
|
||||
vertical-align: middle;
|
||||
background-color: #fff;
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 8px center;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
outline: none;
|
||||
box-shadow: inset 0 1px 2px rgba(0,0,0,0.075);
|
||||
width: inherit;
|
||||
}
|
||||
#file-actions {
|
||||
padding-left: 20px;
|
||||
}
|
||||
.CodeMirror.cm-s-default {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 15px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
height: 600px;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.commit-form-wrapper {
|
||||
padding-left: 64px;
|
||||
}
|
||||
.commit-form {
|
||||
position: relative;
|
||||
padding: 15px;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.commit-form-wrapper .commit-form-avatar {
|
||||
float: left;
|
||||
margin-left: -64px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.commit-form::before {
|
||||
border-width: 8px;
|
||||
border-color: transparent;
|
||||
border-right-color: #ddd;
|
||||
position: absolute;
|
||||
top: 11px;
|
||||
right: 100%;
|
||||
left: -16px;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
pointer-events: none;
|
||||
content: " ";
|
||||
border-style: solid solid outset;
|
||||
}
|
||||
.form-checkbox input[type=checkbox], .form-checkbox input[type=radio] {
|
||||
float: left;
|
||||
margin: 2px 0 0 -20px;
|
||||
vertical-align: middle;
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
}
|
||||
.branch-name {
|
||||
display: inline-block;
|
||||
padding: 2px 6px;
|
||||
font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
color: rgba(0,0,0,0.5);
|
||||
background-color: rgba(209,227,237,0.5);
|
||||
border-radius: 3px;
|
||||
}
|
||||
.form-control, .form-select {
|
||||
min-height: 34px;
|
||||
padding: 7px 8px;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
vertical-align: middle;
|
||||
background-color: #fff;
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 8px center;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
outline: none;
|
||||
box-shadow: inset 0 1px 2px rgba(0,0,0,0.075);
|
||||
}
|
||||
.form-control.input-contrast {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
.form-control.mr-2 {
|
||||
margin-right: 6px !important;
|
||||
}
|
||||
.quick-pull-choice .new-branch-name-input input {
|
||||
width: 240px !important;
|
||||
padding-left: 26px !important;
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
}
|
||||
.quick-pull-choice .new-branch-name-input .quick-pull-new-branch-icon {
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
left: 10px;
|
||||
color: #b0c4ce;
|
||||
}
|
||||
.text-muted, .text-gray {
|
||||
color: #767676 !important;
|
||||
}
|
||||
.quick-pull-choice .new-branch-name-input {
|
||||
position: relative;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.quick-pull-choice .quick-pull-branch-name {
|
||||
display: none;
|
||||
padding-left: 48px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.quick-pull-choice.will-create-branch .quick-pull-branch-name {
|
||||
display: inline-block;
|
||||
}
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
#file-buttons {
|
||||
padding-right: 15px;
|
||||
}
|
||||
.repository .ui.container .ui.breadcrumb {
|
||||
font-size: 1.5em;
|
||||
color: #767676;
|
||||
max-width: 600px;
|
||||
}
|
||||
.repository .ui.container .item:first-child .ui.breadcrumb {
|
||||
max-width: none;
|
||||
}
|
||||
.repository .ui.container .ui.breadcrumb.field {
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
.repo-edit-file-cancel {
|
||||
padding-left: 10px;
|
||||
}
|
||||
#new-branch-item {
|
||||
display:none;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
padding: .71428571em 1.14285714em!important;
|
||||
background: 0 0!important;
|
||||
color: rgba(0,0,0,.87)!important;
|
||||
text-transform: none!important;
|
||||
box-shadow: none!important;
|
||||
-webkit-transition: none!important;
|
||||
transition: none!important;
|
||||
border-top: none;
|
||||
padding-right: calc(1.14285714rem + 17px)!important;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
line-height: 1.1;
|
||||
}
|
||||
#new-branch-item:hover {
|
||||
background: rgba(0,0,0,.05)!important;
|
||||
color: rgba(0,0,0,.95)!important;
|
||||
}
|
||||
#new-branch-item .icon {
|
||||
float: left;
|
||||
margin-left: -15px;
|
||||
}
|
||||
#new-branch-item .description {
|
||||
margin-top: 3px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.repository .ui.container .ui.breadcrumb {
|
||||
font-size: 1.5em;
|
||||
color: #767676;
|
||||
max-width: 600px;
|
||||
}
|
||||
+430
-88
@@ -28,6 +28,61 @@ function initCommentPreviewTab($form) {
|
||||
buttonsClickOnEnter();
|
||||
}
|
||||
|
||||
var previewTab;
|
||||
var previewTabApis;
|
||||
|
||||
function initEditPreviewTab($form) {
|
||||
var $tab_menu = $form.find('.tabular.menu');
|
||||
$tab_menu.find('.item').tab();
|
||||
previewTab = $tab_menu.find('.item[data-tab="' + $tab_menu.data('preview') + '"]');
|
||||
|
||||
if (previewTab.length) {
|
||||
previewTabApis = previewTab.data('preview-apis').split(',');
|
||||
previewTab.click(function () {
|
||||
var $this = $(this);
|
||||
$.post($this.data('url'), {
|
||||
"_csrf": csrf,
|
||||
"mode": "gfm",
|
||||
"context": $this.data('context'),
|
||||
"text": $form.find('.tab.segment[data-tab="' + $tab_menu.data('write') + '"] textarea').val()
|
||||
},
|
||||
function (data) {
|
||||
var $preview_tab = $form.find('.tab.segment[data-tab="' + $tab_menu.data('preview') + '"]');
|
||||
$preview_tab.html(data);
|
||||
emojify.run($preview_tab[0]);
|
||||
$('pre code', $preview_tab[0]).each(function (i, block) {
|
||||
hljs.highlightBlock(block);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
buttonsClickOnEnter();
|
||||
}
|
||||
|
||||
function initEditDiffTab($form) {
|
||||
var $tab_menu = $form.find('.tabular.menu');
|
||||
$tab_menu.find('.item').tab();
|
||||
$tab_menu.find('.item[data-tab="' + $tab_menu.data('diff') + '"]').click(function () {
|
||||
var $this = $(this);
|
||||
$.post($this.data('url'), {
|
||||
"_csrf": csrf,
|
||||
"context": $this.data('context'),
|
||||
"content": $form.find('.tab.segment[data-tab="' + $tab_menu.data('write') + '"] textarea').val()
|
||||
},
|
||||
function (data) {
|
||||
var $diff_tab = $form.find('.tab.segment[data-tab="' + $tab_menu.data('diff') + '"]');
|
||||
$diff_tab.html(data);
|
||||
emojify.run($diff_tab[0]);
|
||||
initCodeView()
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
buttonsClickOnEnter();
|
||||
}
|
||||
|
||||
function initCommentForm() {
|
||||
if ($('.comment.form').length == 0) {
|
||||
return
|
||||
@@ -145,6 +200,11 @@ function initCommentForm() {
|
||||
selectItem('.select-assignee', '#assignee_id');
|
||||
}
|
||||
|
||||
function initEditForm() {
|
||||
initEditPreviewTab($('.edit.form'));
|
||||
initEditDiffTab($('.edit.form'));
|
||||
}
|
||||
|
||||
function initInstall() {
|
||||
if ($('.install').length == 0) {
|
||||
return;
|
||||
@@ -450,7 +510,7 @@ function initRepository() {
|
||||
|
||||
// Change status
|
||||
var $status_btn = $('#status-button');
|
||||
$('#content').keyup(function () {
|
||||
$('#edit_area').keyup(function () {
|
||||
if ($(this).val().length == 0) {
|
||||
$status_btn.text($status_btn.data('status'))
|
||||
} else {
|
||||
@@ -516,15 +576,10 @@ function initRepositoryCollaboration() {
|
||||
});
|
||||
}
|
||||
|
||||
function initWiki() {
|
||||
if ($('.repository.wiki').length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ($('.repository.wiki.new').length > 0) {
|
||||
var $edit_area = $('#edit-area');
|
||||
var simplemde = new SimpleMDE({
|
||||
function initWikiForm() {
|
||||
var $edit_area = $('.repository.wiki textarea#edit_area');
|
||||
if ($edit_area.length > 0) {
|
||||
new SimpleMDE({
|
||||
autoDownloadFontAwesome: false,
|
||||
element: $edit_area[0],
|
||||
forceSync: true,
|
||||
@@ -549,18 +604,284 @@ function initWiki() {
|
||||
renderingConfig: {
|
||||
singleLineBreaks: false
|
||||
},
|
||||
spellChecker: false,
|
||||
indentWithTabs: false,
|
||||
tabSize: 4,
|
||||
spellChecker: false,
|
||||
toolbar: ["bold", "italic", "strikethrough", "|",
|
||||
"heading", "heading-1", "heading-2", "heading-3", "|",
|
||||
"heading-1", "heading-2", "heading-3", "heading-bigger", "heading-smaller", "|",
|
||||
"code", "quote", "|",
|
||||
"unordered-list", "ordered-list", "|",
|
||||
"link", "image", "horizontal-rule", "|",
|
||||
"preview", "fullscreen"]
|
||||
"link", "image", "table", "horizontal-rule", "|",
|
||||
"clean-block", "preview", "fullscreen", "side-by-side"]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function initIssueForm() {
|
||||
var $edit_area = $('.repository.issue textarea.edit_area');
|
||||
if ($edit_area.length > 0) {
|
||||
$edit_area.each(function (i, edit_area) {
|
||||
new SimpleMDE({
|
||||
autoDownloadFontAwesome: false,
|
||||
element: edit_area[0],
|
||||
forceSync: true,
|
||||
previewRender: function (plainText, preview) { // Async method
|
||||
setTimeout(function () {
|
||||
// FIXME: still send render request when return back to edit mode
|
||||
$.post($edit_area.data('url'), {
|
||||
"_csrf": csrf,
|
||||
"mode": "gfm",
|
||||
"context": $edit_area.data('context'),
|
||||
"text": plainText
|
||||
},
|
||||
function (data) {
|
||||
preview.innerHTML = '<div class="markdown">' + data + '</div>';
|
||||
emojify.run($('.editor-preview')[0]);
|
||||
}
|
||||
);
|
||||
}, 0);
|
||||
|
||||
return "Loading...";
|
||||
},
|
||||
renderingConfig: {
|
||||
singleLineBreaks: false
|
||||
},
|
||||
indentWithTabs: false,
|
||||
tabSize: 4,
|
||||
spellChecker: false,
|
||||
toolbar: ["bold", "italic", "strikethrough", "|",
|
||||
"code", "quote", "|",
|
||||
"unordered-list", "ordered-list", "|",
|
||||
"link", "image", "table"]
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var editArea;
|
||||
var editFilename;
|
||||
var smdEditor;
|
||||
var cmEditor;
|
||||
var mdFileExtensions;
|
||||
var lineWrapExtensions;
|
||||
|
||||
// For IE
|
||||
String.prototype.endsWith = function (pattern) {
|
||||
var d = this.length - pattern.length;
|
||||
return d >= 0 && this.lastIndexOf(pattern) === d;
|
||||
};
|
||||
|
||||
// Adding function to get the cursor position in a text field to jquery objects
|
||||
(function ($, undefined) {
|
||||
$.fn.getCursorPosition = function () {
|
||||
var el = $(this).get(0);
|
||||
var pos = 0;
|
||||
if ('selectionStart' in el) {
|
||||
pos = el.selectionStart;
|
||||
} else if ('selection' in document) {
|
||||
el.focus();
|
||||
var Sel = document.selection.createRange();
|
||||
var SelLength = document.selection.createRange().text.length;
|
||||
Sel.moveStart('character', -el.value.length);
|
||||
pos = Sel.text.length - SelLength;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
})(jQuery);
|
||||
|
||||
function initEditor() {
|
||||
editFilename = $("#file-name");
|
||||
editFilename.keyup(function (e) {
|
||||
var sections = $('.breadcrumb span.section');
|
||||
var dividers = $('.breadcrumb div.divider');
|
||||
if (e.keyCode == 8) {
|
||||
if ($(this).getCursorPosition() == 0) {
|
||||
if (sections.length > 0) {
|
||||
var value = sections.last().find('a').text();
|
||||
$(this).val(value + $(this).val());
|
||||
$(this)[0].setSelectionRange(value.length, value.length);
|
||||
sections.last().remove();
|
||||
dividers.last().remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (e.keyCode == 191) {
|
||||
var parts = $(this).val().split('/');
|
||||
for (var i = 0; i < parts.length; ++i) {
|
||||
var value = parts[i];
|
||||
if (i < parts.length - 1) {
|
||||
if (value.length) {
|
||||
$('<span class="section"><a href="#">' + value + '</a></span>').insertBefore($(this));
|
||||
$('<div class="divider"> / </div>').insertBefore($(this));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$(this).val(value);
|
||||
}
|
||||
$(this)[0].setSelectionRange(0, 0);
|
||||
}
|
||||
}
|
||||
var parts = [];
|
||||
$('.breadcrumb span.section').each(function (i, element) {
|
||||
element = $(element);
|
||||
if (element.find('a').length) {
|
||||
parts.push(element.find('a').text());
|
||||
} else {
|
||||
parts.push(element.text());
|
||||
}
|
||||
});
|
||||
if ($(this).val())
|
||||
parts.push($(this).val());
|
||||
$('#tree-name').val(parts.join('/'));
|
||||
}).trigger('keyup');
|
||||
|
||||
editArea = $('.repository.edit textarea#edit_area');
|
||||
|
||||
if (!editArea.length)
|
||||
return;
|
||||
|
||||
mdFileExtensions = editArea.data("md-file-extensions").split(",");
|
||||
lineWrapExtensions = editArea.data("line-wrap-extensions").split(",");
|
||||
|
||||
editFilename.on("keyup", function (e) {
|
||||
var val = editFilename.val(), m, mode, spec, extension, extWithDot, previewLink, dataUrl, apiCall;
|
||||
extension = extWithDot = "";
|
||||
if (m = /.+\.([^.]+)$/.exec(val)) {
|
||||
extension = m[1];
|
||||
extWithDot = "." + extension;
|
||||
}
|
||||
|
||||
var info = CodeMirror.findModeByExtension(extension);
|
||||
previewLink = $('a[data-tab=preview]');
|
||||
if (info) {
|
||||
mode = info.mode;
|
||||
spec = info.mime;
|
||||
apiCall = mode;
|
||||
}
|
||||
else {
|
||||
apiCall = extension
|
||||
}
|
||||
|
||||
if (previewLink.length && apiCall && previewTabApis && previewTabApis.length && previewTabApis.indexOf(apiCall) >= 0) {
|
||||
dataUrl = previewLink.data('url');
|
||||
previewLink.data('url', dataUrl.replace(/(.*)\/.*/i, '$1/' + mode));
|
||||
previewLink.show();
|
||||
}
|
||||
else {
|
||||
previewLink.hide();
|
||||
}
|
||||
|
||||
// If this file is a Markdown extensions, we will load that editor and return
|
||||
if (mdFileExtensions.indexOf(extWithDot) >= 0) {
|
||||
if (setSimpleMDE()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Else we are going to use CodeMirror
|
||||
if (!cmEditor) {
|
||||
if (!setCodeMirror())
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode) {
|
||||
cmEditor.setOption("mode", spec);
|
||||
CodeMirror.autoLoadMode(cmEditor, mode);
|
||||
}
|
||||
|
||||
if (lineWrapExtensions.indexOf(extWithDot) >= 0) {
|
||||
cmEditor.setOption("lineWrapping", true);
|
||||
}
|
||||
else {
|
||||
cmEditor.setOption("lineWrapping", false);
|
||||
}
|
||||
}).trigger('keyup');
|
||||
}
|
||||
|
||||
function setSimpleMDE() {
|
||||
if (cmEditor) {
|
||||
cmEditor.toTextArea();
|
||||
cmEditor = null;
|
||||
}
|
||||
|
||||
if (smdEditor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
smdEditor = new SimpleMDE({
|
||||
autoDownloadFontAwesome: false,
|
||||
element: editArea[0],
|
||||
forceSync: true,
|
||||
renderingConfig: {
|
||||
singleLineBreaks: false
|
||||
},
|
||||
indentWithTabs: false,
|
||||
tabSize: 4,
|
||||
spellChecker: false,
|
||||
previewRender: function (plainText, preview) { // Async method
|
||||
setTimeout(function () {
|
||||
// FIXME: still send render request when return back to edit mode
|
||||
$.post(editArea.data('url'), {
|
||||
"_csrf": csrf,
|
||||
"mode": "gfm",
|
||||
"context": editArea.data('context'),
|
||||
"text": plainText
|
||||
},
|
||||
function (data) {
|
||||
preview.innerHTML = '<div class="markdown">' + data + '</div>';
|
||||
emojify.run($('.editor-preview')[0]);
|
||||
}
|
||||
);
|
||||
}, 0);
|
||||
|
||||
return "Loading...";
|
||||
},
|
||||
toolbar: ["bold", "italic", "strikethrough", "|",
|
||||
"heading-1", "heading-2", "heading-3", "heading-bigger", "heading-smaller", "|",
|
||||
"code", "quote", "|",
|
||||
"unordered-list", "ordered-list", "|",
|
||||
"link", "image", "table", "horizontal-rule", "|",
|
||||
"clean-block", "preview", "fullscreen", "side-by-side"]
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function setCodeMirror() {
|
||||
if (smdEditor) {
|
||||
smdEditor.toTextArea();
|
||||
smdEditor = null;
|
||||
}
|
||||
|
||||
if (cmEditor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
cmEditor = CodeMirror.fromTextArea(editArea[0], {
|
||||
lineNumbers: true
|
||||
});
|
||||
cmEditor.on("change", function (cm, change) {
|
||||
editArea.val(cm.getValue());
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function initQuickPull() {
|
||||
$('.js-quick-pull-choice-option').change(function () {
|
||||
quickPullChoiceChange();
|
||||
});
|
||||
quickPullChoiceChange();
|
||||
}
|
||||
|
||||
function quickPullChoiceChange() {
|
||||
var radio = $('.js-quick-pull-choice-option:checked');
|
||||
if (radio.val() == 'commit-to-new-branch')
|
||||
$('.quick-pull-branch-name').show();
|
||||
else
|
||||
$('.quick-pull-branch-name').hide();
|
||||
}
|
||||
|
||||
function initOrganization() {
|
||||
if ($('.organization').length == 0) {
|
||||
return;
|
||||
@@ -867,6 +1188,37 @@ function searchRepositories() {
|
||||
hideWhenLostFocus('#search-repo-box .results', '#search-repo-box');
|
||||
}
|
||||
|
||||
function initCodeView() {
|
||||
if ($('.code-view .linenums').length > 0) {
|
||||
$(document).on('click', '.lines-num span', function (e) {
|
||||
var $select = $(this);
|
||||
var $list = $select.parent().siblings('.lines-code').find('ol.linenums > li');
|
||||
selectRange($list, $list.filter('[rel=' + $select.attr('id') + ']'), (e.shiftKey ? $list.filter('.active').eq(0) : null));
|
||||
deSelect();
|
||||
});
|
||||
|
||||
$(window).on('hashchange', function (e) {
|
||||
var m = window.location.hash.match(/^#(L\d+)\-(L\d+)$/);
|
||||
var $list = $('.code-view ol.linenums > li');
|
||||
var $first;
|
||||
if (m) {
|
||||
$first = $list.filter('.' + m[1]);
|
||||
selectRange($list, $first, $list.filter('.' + m[2]));
|
||||
$("html, body").scrollTop($first.offset().top - 200);
|
||||
return;
|
||||
}
|
||||
m = window.location.hash.match(/^#(L\d+)$/);
|
||||
if (m) {
|
||||
$first = $list.filter('.' + m[1]);
|
||||
selectRange($list, $first);
|
||||
$("html, body").scrollTop($first.offset().top - 200);
|
||||
}
|
||||
}).trigger('hashchange');
|
||||
}
|
||||
}
|
||||
|
||||
var $dropz;
|
||||
|
||||
$(document).ready(function () {
|
||||
csrf = $('meta[name=_csrf]').attr("content");
|
||||
suburl = $('meta[name=_suburl]').attr("content");
|
||||
@@ -916,12 +1268,12 @@ $(document).ready(function () {
|
||||
}
|
||||
|
||||
// Dropzone
|
||||
if ($('#dropzone').length > 0) {
|
||||
var $dropz = $('#dropzone');
|
||||
if ($dropz.length > 0) {
|
||||
// Disable auto discover for all elements:
|
||||
Dropzone.autoDiscover = false;
|
||||
|
||||
var filenameDict = {};
|
||||
var $dropz = $('#dropzone');
|
||||
$dropz.dropzone({
|
||||
url: $dropz.data('upload-url'),
|
||||
headers: {"X-Csrf-Token": csrf},
|
||||
@@ -936,12 +1288,16 @@ $(document).ready(function () {
|
||||
init: function () {
|
||||
this.on("success", function (file, data) {
|
||||
filenameDict[file.name] = data.uuid;
|
||||
$('.attachments').append('<input id="' + data.uuid + '" name="attachments" type="hidden" value="' + data.uuid + '">');
|
||||
var input = $('<input id="' + data.uuid + '" name="files" type="hidden">').val(data.uuid);
|
||||
$('.files').append(input);
|
||||
});
|
||||
this.on("removedfile", function (file) {
|
||||
if (file.name in filenameDict) {
|
||||
$('#' + filenameDict[file.name]).remove();
|
||||
}
|
||||
if ($dropz.data('remove-url') && $dropz.data('csrf')) {
|
||||
$.post($dropz.data('remove-url'), {file: filenameDict[file.name], _csrf: $dropz.data('csrf')});
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -975,6 +1331,15 @@ $(document).ready(function () {
|
||||
e.trigger.setAttribute('data-content', e.trigger.getAttribute('data-original'))
|
||||
});
|
||||
|
||||
// Clipboard for copying filename on edit page
|
||||
if ($('.clipboard-tree-name').length) {
|
||||
new Clipboard(document.querySelector('.clipboard-tree-name'), {
|
||||
text: function () {
|
||||
return $('#tree-name').val();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Helpers.
|
||||
$('.delete-button').click(function () {
|
||||
var $this = $(this);
|
||||
@@ -1038,10 +1403,14 @@ $(document).ready(function () {
|
||||
initCommentForm();
|
||||
initInstall();
|
||||
initRepository();
|
||||
initWiki();
|
||||
initWikiForm();
|
||||
initIssueForm();
|
||||
initEditForm();
|
||||
initEditor();
|
||||
initOrganization();
|
||||
initWebhook();
|
||||
initAdmin();
|
||||
initQuickPull();
|
||||
|
||||
var routes = {
|
||||
'div.user.settings': initUserSettings,
|
||||
@@ -1057,76 +1426,50 @@ $(document).ready(function () {
|
||||
}
|
||||
});
|
||||
|
||||
function changeHash(hash) {
|
||||
if (history.pushState) {
|
||||
history.pushState(null, null, hash);
|
||||
}
|
||||
else {
|
||||
location.hash = hash;
|
||||
}
|
||||
}
|
||||
|
||||
function deSelect() {
|
||||
if (window.getSelection) {
|
||||
window.getSelection().removeAllRanges();
|
||||
} else {
|
||||
document.selection.empty();
|
||||
}
|
||||
}
|
||||
|
||||
function selectRange($list, $select, $from) {
|
||||
$list.removeClass('active');
|
||||
if ($from) {
|
||||
var a = parseInt($select.attr('rel').substr(1));
|
||||
var b = parseInt($from.attr('rel').substr(1));
|
||||
var c;
|
||||
if (a != b) {
|
||||
if (a > b) {
|
||||
c = a;
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
var classes = [];
|
||||
for (var i = a; i <= b; i++) {
|
||||
classes.push('.L' + i);
|
||||
}
|
||||
$list.filter(classes.join(',')).addClass('active');
|
||||
changeHash('#L' + a + '-' + 'L' + b);
|
||||
return
|
||||
}
|
||||
}
|
||||
$select.addClass('active');
|
||||
changeHash('#' + $select.attr('rel'));
|
||||
}
|
||||
|
||||
$(window).load(function () {
|
||||
function changeHash(hash) {
|
||||
if (history.pushState) {
|
||||
history.pushState(null, null, hash);
|
||||
}
|
||||
else {
|
||||
location.hash = hash;
|
||||
}
|
||||
}
|
||||
|
||||
function deSelect() {
|
||||
if (window.getSelection) {
|
||||
window.getSelection().removeAllRanges();
|
||||
} else {
|
||||
document.selection.empty();
|
||||
}
|
||||
}
|
||||
|
||||
function selectRange($list, $select, $from) {
|
||||
$list.removeClass('active');
|
||||
if ($from) {
|
||||
var a = parseInt($select.attr('rel').substr(1));
|
||||
var b = parseInt($from.attr('rel').substr(1));
|
||||
var c;
|
||||
if (a != b) {
|
||||
if (a > b) {
|
||||
c = a;
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
var classes = [];
|
||||
for (var i = a; i <= b; i++) {
|
||||
classes.push('.L' + i);
|
||||
}
|
||||
$list.filter(classes.join(',')).addClass('active');
|
||||
changeHash('#L' + a + '-' + 'L' + b);
|
||||
return
|
||||
}
|
||||
}
|
||||
$select.addClass('active');
|
||||
changeHash('#' + $select.attr('rel'));
|
||||
}
|
||||
|
||||
// Code view.
|
||||
if ($('.code-view .linenums').length > 0) {
|
||||
$(document).on('click', '.lines-num span', function (e) {
|
||||
var $select = $(this);
|
||||
var $list = $select.parent().siblings('.lines-code').find('ol.linenums > li');
|
||||
selectRange($list, $list.filter('[rel=' + $select.attr('id') + ']'), (e.shiftKey ? $list.filter('.active').eq(0) : null));
|
||||
deSelect();
|
||||
});
|
||||
|
||||
$(window).on('hashchange', function (e) {
|
||||
var m = window.location.hash.match(/^#(L\d+)\-(L\d+)$/);
|
||||
var $list = $('.code-view ol.linenums > li');
|
||||
var $first;
|
||||
if (m) {
|
||||
$first = $list.filter('.' + m[1]);
|
||||
selectRange($list, $first, $list.filter('.' + m[2]));
|
||||
$("html, body").scrollTop($first.offset().top - 200);
|
||||
return;
|
||||
}
|
||||
m = window.location.hash.match(/^#(L\d+)$/);
|
||||
if (m) {
|
||||
$first = $list.filter('.' + m[1]);
|
||||
selectRange($list, $first);
|
||||
$("html, body").scrollTop($first.offset().top - 200);
|
||||
}
|
||||
}).trigger('hashchange');
|
||||
}
|
||||
initCodeView();
|
||||
|
||||
// Repo clone url.
|
||||
if ($('#repo-clone-url').length > 0) {
|
||||
@@ -1135,7 +1478,6 @@ $(window).load(function () {
|
||||
if ($('#repo-clone-ssh').click().length === 0) {
|
||||
$('#repo-clone-https').click();
|
||||
}
|
||||
;
|
||||
break;
|
||||
default:
|
||||
$('#repo-clone-https').click();
|
||||
|
||||
@@ -5,8 +5,13 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -29,3 +34,53 @@ func Branches(ctx *context.Context) {
|
||||
ctx.Data["Branches"] = brs
|
||||
ctx.HTML(200, BRANCH)
|
||||
}
|
||||
|
||||
func NewBranchPost(ctx *context.Context, form auth.NewBranchForm) {
|
||||
oldBranchName := form.OldBranchName
|
||||
branchName := form.BranchName
|
||||
|
||||
if ctx.HasError() || !ctx.Repo.IsWriter() || branchName == oldBranchName {
|
||||
ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/src/" + oldBranchName))
|
||||
return
|
||||
}
|
||||
|
||||
branchName = url.QueryEscape(strings.Replace(strings.Trim(branchName, " "), " ", "-", -1))
|
||||
|
||||
if _, err := ctx.Repo.Repository.GetBranch(branchName); err == nil {
|
||||
ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/src/" + branchName))
|
||||
return
|
||||
}
|
||||
|
||||
if err := ctx.Repo.Repository.CreateNewBranch(ctx.User, oldBranchName, branchName); err != nil {
|
||||
ctx.Handle(404, "repo.Branches(CreateNewBranch)", err)
|
||||
log.Error(4, "%s: %v", "EditFile", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Was successful, so now need to call models.CommitRepoAction() with the new commitID for webhooks and watchers
|
||||
if branch, err := ctx.Repo.Repository.GetBranch(branchName); err != nil {
|
||||
log.Error(4, "repo.Repository.GetBranch(%s): %v", branchName, err)
|
||||
} else if commit, err := branch.GetCommit(); err != nil {
|
||||
log.Error(4, "branch.GetCommit(): %v", err)
|
||||
} else {
|
||||
pc := &models.PushCommits{
|
||||
Len: 1,
|
||||
Commits: []*models.PushCommit{&models.PushCommit{
|
||||
commit.ID.String(),
|
||||
commit.Message(),
|
||||
commit.Author.Email,
|
||||
commit.Author.Name,
|
||||
}},
|
||||
}
|
||||
oldCommitID := "0000000000000000000000000000000000000000" // New Branch so we use all 0s
|
||||
newCommitID := commit.ID.String()
|
||||
if err := models.CommitRepoAction(ctx.User.ID, ctx.Repo.Owner.ID, ctx.User.LowerName, ctx.Repo.Owner.Email,
|
||||
ctx.Repo.Repository.ID, ctx.Repo.Owner.LowerName, ctx.Repo.Repository.Name, "refs/heads/"+branchName, pc,
|
||||
oldCommitID, newCommitID); err != nil {
|
||||
log.Error(4, "models.CommitRepoAction(branch = %s): %v", branchName, err)
|
||||
}
|
||||
models.HookQueue.Add(ctx.Repo.Repository.ID)
|
||||
}
|
||||
|
||||
ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/src/" + branchName))
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright 2016 The Gogs 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 repo
|
||||
|
||||
import (
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
)
|
||||
|
||||
func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
|
||||
branchName := ctx.Repo.BranchName
|
||||
treeName := ctx.Repo.TreeName
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName + "/" + treeName)
|
||||
return
|
||||
}
|
||||
|
||||
if err := ctx.Repo.Repository.DeleteRepoFile(ctx.User, branchName, treeName, form.CommitSummary); err != nil {
|
||||
ctx.Handle(500, "DeleteRepoFile", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Was successful, so now need to call models.CommitRepoAction() with the new commitID for webhooks and watchers
|
||||
if branch, err := ctx.Repo.Repository.GetBranch(branchName); err != nil {
|
||||
log.Error(4, "repo.Repository.GetBranch(%s): %v", branchName, err)
|
||||
} else if commit, err := branch.GetCommit(); err != nil {
|
||||
log.Error(4, "branch.GetCommit(): %v", err)
|
||||
} else {
|
||||
pc := &models.PushCommits{
|
||||
Len: 1,
|
||||
Commits: []*models.PushCommit{&models.PushCommit{
|
||||
commit.ID.String(),
|
||||
commit.Message(),
|
||||
commit.Author.Email,
|
||||
commit.Author.Name,
|
||||
}},
|
||||
}
|
||||
oldCommitID := ctx.Repo.CommitID
|
||||
newCommitID := commit.ID.String()
|
||||
if err := models.CommitRepoAction(ctx.User.ID, ctx.Repo.Owner.ID, ctx.User.LowerName, ctx.Repo.Owner.Email,
|
||||
ctx.Repo.Repository.ID, ctx.Repo.Owner.LowerName, ctx.Repo.Repository.Name, "refs/heads/"+branchName, pc,
|
||||
oldCommitID, newCommitID); err != nil {
|
||||
log.Error(4, "models.CommitRepoAction(branch = %s): %v", branchName, err)
|
||||
}
|
||||
models.HookQueue.Add(ctx.Repo.Repository.ID)
|
||||
}
|
||||
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName)
|
||||
}
|
||||
@@ -0,0 +1,359 @@
|
||||
// Copyright 2016 The Gogs 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 repo
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/gogits/git-module"
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
"github.com/gogits/gogs/modules/template"
|
||||
)
|
||||
|
||||
const (
|
||||
EDIT base.TplName = "repo/edit"
|
||||
DIFF_PREVIEW base.TplName = "repo/diff_preview"
|
||||
DIFF_PREVIEW_NEW base.TplName = "repo/diff_preview_new"
|
||||
)
|
||||
|
||||
func EditFile(ctx *context.Context) {
|
||||
editFile(ctx, false)
|
||||
}
|
||||
|
||||
func NewFile(ctx *context.Context) {
|
||||
editFile(ctx, true)
|
||||
}
|
||||
|
||||
func editFile(ctx *context.Context, isNewFile bool) {
|
||||
ctx.Data["PageIsEdit"] = true
|
||||
ctx.Data["IsNewFile"] = isNewFile
|
||||
ctx.Data["RequireHighlightJS"] = true
|
||||
|
||||
userName := ctx.Repo.Owner.Name
|
||||
repoName := ctx.Repo.Repository.Name
|
||||
branchName := ctx.Repo.BranchName
|
||||
branchLink := ctx.Repo.RepoLink + "/src/" + branchName
|
||||
treeName := ctx.Repo.TreeName
|
||||
|
||||
var treeNames []string
|
||||
if len(treeName) > 0 {
|
||||
treeNames = strings.Split(treeName, "/")
|
||||
}
|
||||
|
||||
if !isNewFile {
|
||||
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treeName)
|
||||
|
||||
if err != nil && git.IsErrNotExist(err) {
|
||||
ctx.Handle(404, "GetTreeEntryByPath", err)
|
||||
return
|
||||
}
|
||||
|
||||
if (ctx.Repo.IsViewCommit) || entry == nil || entry.IsDir() {
|
||||
ctx.Handle(404, "repo.Home", nil)
|
||||
return
|
||||
}
|
||||
|
||||
blob := entry.Blob()
|
||||
|
||||
dataRc, err := blob.Data()
|
||||
if err != nil {
|
||||
ctx.Handle(404, "blob.Data", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["FileSize"] = blob.Size()
|
||||
ctx.Data["FileName"] = blob.Name()
|
||||
|
||||
buf := make([]byte, 1024)
|
||||
n, _ := dataRc.Read(buf)
|
||||
if n > 0 {
|
||||
buf = buf[:n]
|
||||
}
|
||||
|
||||
_, isTextFile := base.IsTextFile(buf)
|
||||
|
||||
if !isTextFile {
|
||||
ctx.Handle(404, "repo.Home", nil)
|
||||
return
|
||||
}
|
||||
|
||||
d, _ := ioutil.ReadAll(dataRc)
|
||||
buf = append(buf, d...)
|
||||
|
||||
if err, content := template.ToUtf8WithErr(buf); err != nil {
|
||||
if err != nil {
|
||||
log.Error(4, "Convert content encoding: %s", err)
|
||||
}
|
||||
ctx.Data["FileContent"] = string(buf)
|
||||
} else {
|
||||
ctx.Data["FileContent"] = content
|
||||
}
|
||||
} else {
|
||||
treeNames = append(treeNames, "")
|
||||
}
|
||||
|
||||
ctx.Data["RequireSimpleMDE"] = true
|
||||
|
||||
ctx.Data["UserName"] = userName
|
||||
ctx.Data["RepoName"] = repoName
|
||||
ctx.Data["BranchName"] = branchName
|
||||
ctx.Data["TreeName"] = treeName
|
||||
ctx.Data["TreeNames"] = treeNames
|
||||
ctx.Data["BranchLink"] = branchLink
|
||||
ctx.Data["CommitSummary"] = ""
|
||||
ctx.Data["CommitMessage"] = ""
|
||||
ctx.Data["CommitChoice"] = "direct"
|
||||
ctx.Data["NewBranchName"] = ""
|
||||
ctx.Data["CommitDirectlyToThisBranch"] = ctx.Tr("repo.commit_directly_to_this_branch", "<strong class=\"branch-name\">"+branchName+"</strong>")
|
||||
ctx.Data["CreateNewBranch"] = ctx.Tr("repo.create_new_branch", "<strong>"+ctx.Tr("repo.new_branch")+"</strong>")
|
||||
ctx.Data["LastCommit"] = ctx.Repo.Commit.ID
|
||||
ctx.Data["MdFileExtensions"] = strings.Join(setting.Markdown.MdFileExtensions, ",")
|
||||
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Editor.LineWrapExtensions, ",")
|
||||
ctx.Data["PreviewTabApis"] = strings.Join(setting.Editor.PreviewTabApis, ",")
|
||||
ctx.Data["PreviewDiffUrl"] = ctx.Repo.RepoLink + "/preview/" + branchName + "/" + treeName
|
||||
|
||||
ctx.HTML(200, EDIT)
|
||||
}
|
||||
|
||||
func EditFilePost(ctx *context.Context, form auth.EditRepoFileForm) {
|
||||
editFilePost(ctx, form, false)
|
||||
}
|
||||
|
||||
func NewFilePost(ctx *context.Context, form auth.EditRepoFileForm) {
|
||||
editFilePost(ctx, form, true)
|
||||
}
|
||||
|
||||
func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bool) {
|
||||
ctx.Data["PageIsEdit"] = true
|
||||
ctx.Data["IsNewFile"] = isNewFile
|
||||
ctx.Data["RequireHighlightJS"] = true
|
||||
|
||||
userName := ctx.Repo.Owner.Name
|
||||
repoName := ctx.Repo.Repository.Name
|
||||
oldBranchName := ctx.Repo.BranchName
|
||||
branchName := oldBranchName
|
||||
branchLink := ctx.Repo.RepoLink + "/src/" + branchName
|
||||
oldTreeName := ctx.Repo.TreeName
|
||||
content := form.Content
|
||||
commitChoice := form.CommitChoice
|
||||
lastCommit := form.LastCommit
|
||||
|
||||
if commitChoice == "commit-to-new-branch" {
|
||||
branchName = form.NewBranchName
|
||||
}
|
||||
|
||||
treeName := form.TreeName
|
||||
treeName = strings.Trim(treeName, " ")
|
||||
treeName = strings.Trim(treeName, "/")
|
||||
|
||||
var treeNames []string
|
||||
if len(treeName) > 0 {
|
||||
treeNames = strings.Split(treeName, "/")
|
||||
}
|
||||
|
||||
ctx.Data["RequireSimpleMDE"] = true
|
||||
|
||||
ctx.Data["UserName"] = userName
|
||||
ctx.Data["RepoName"] = repoName
|
||||
ctx.Data["BranchName"] = branchName
|
||||
ctx.Data["TreeName"] = treeName
|
||||
ctx.Data["TreeNames"] = treeNames
|
||||
ctx.Data["BranchLink"] = branchLink
|
||||
ctx.Data["FileContent"] = content
|
||||
ctx.Data["CommitSummary"] = form.CommitSummary
|
||||
ctx.Data["CommitMessage"] = form.CommitMessage
|
||||
ctx.Data["CommitChoice"] = commitChoice
|
||||
ctx.Data["NewBranchName"] = branchName
|
||||
ctx.Data["CommitDirectlyToThisBranch"] = ctx.Tr("repo.commit_directly_to_this_branch", "<strong class=\"branch-name\">"+oldBranchName+"</strong>")
|
||||
ctx.Data["CreateNewBranch"] = ctx.Tr("repo.create_new_branch", "<strong>"+ctx.Tr("repo.new_branch")+"</strong>")
|
||||
ctx.Data["LastCommit"] = ctx.Repo.Commit.ID
|
||||
ctx.Data["MdFileExtensions"] = strings.Join(setting.Markdown.MdFileExtensions, ",")
|
||||
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Editor.LineWrapExtensions, ",")
|
||||
ctx.Data["PreviewTabApis"] = strings.Join(setting.Editor.PreviewTabApis, ",")
|
||||
ctx.Data["PreviewDiffUrl"] = ctx.Repo.RepoLink + "/preview/" + branchName + "/" + treeName
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.HTML(200, EDIT)
|
||||
return
|
||||
}
|
||||
|
||||
if len(treeName) == 0 {
|
||||
ctx.Data["Err_Filename"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.filename_cannot_be_empty"), EDIT, &form)
|
||||
log.Error(4, "%s: %s", "EditFile", "Filename can't be empty")
|
||||
return
|
||||
}
|
||||
|
||||
if oldBranchName != branchName {
|
||||
if _, err := ctx.Repo.Repository.GetBranch(branchName); err == nil {
|
||||
ctx.Data["Err_Branchname"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.branch_already_exists"), EDIT, &form)
|
||||
log.Error(4, "%s: %s - %s", "BranchName", branchName, "Branch already exists")
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
treepath := ""
|
||||
for index, part := range treeNames {
|
||||
treepath = path.Join(treepath, part)
|
||||
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treepath)
|
||||
if err != nil {
|
||||
// Means there is no item with that name, so we're good
|
||||
break
|
||||
}
|
||||
if index != len(treeNames)-1 {
|
||||
if !entry.IsDir() {
|
||||
ctx.Data["Err_Filename"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.directory_is_a_file"), EDIT, &form)
|
||||
log.Error(4, "%s: %s - %s", "EditFile", treeName, "Directory given is a file")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if entry.IsDir() {
|
||||
ctx.Data["Err_Filename"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.filename_is_a_directory"), EDIT, &form)
|
||||
log.Error(4, "%s: %s - %s", "EditFile", treeName, "Filename given is a dirctory")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !isNewFile {
|
||||
_, err := ctx.Repo.Commit.GetTreeEntryByPath(oldTreeName)
|
||||
if err != nil && git.IsErrNotExist(err) {
|
||||
ctx.Data["Err_Filename"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.file_editing_no_longer_exists"), EDIT, &form)
|
||||
log.Error(4, "%s: %s / %s - %s", "EditFile", branchName, oldTreeName, "File doesn't exist for editing")
|
||||
return
|
||||
}
|
||||
if lastCommit != ctx.Repo.CommitID {
|
||||
if files, err := ctx.Repo.Commit.GetFilesChangedSinceCommit(lastCommit); err == nil {
|
||||
for _, file := range files {
|
||||
if file == treeName {
|
||||
name := ctx.Repo.Commit.Author.Name
|
||||
if u, err := models.GetUserByEmail(ctx.Repo.Commit.Author.Email); err == nil {
|
||||
name = `<a href="` + setting.AppSubUrl + "/" + u.Name + `" target="_blank">` + u.Name + `</a>`
|
||||
}
|
||||
message := ctx.Tr("repo.user_has_committed_since_you_started_editing", name) +
|
||||
` <a href="` + ctx.Repo.RepoLink + "/commit/" + ctx.Repo.CommitID + `" target="_blank">` + ctx.Tr("repo.see_what_changed") + `</a>` +
|
||||
" " + ctx.Tr("repo.pressing_commit_again_will_overwrite_those_changes", "<em>"+ctx.Tr("repo.commit_changes")+"</em>")
|
||||
log.Error(4, "%s: %s / %s - %s", "EditFile", branchName, oldTreeName, "File updated by another user")
|
||||
ctx.RenderWithErr(message, EDIT, &form)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if oldTreeName != treeName {
|
||||
// We have a new filename (rename or completely new file) so we need to make sure it doesn't already exist, can't clobber
|
||||
_, err := ctx.Repo.Commit.GetTreeEntryByPath(treeName)
|
||||
if err == nil {
|
||||
ctx.Data["Err_Filename"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.file_already_exists"), EDIT, &form)
|
||||
log.Error(4, "%s: %s - %s", "NewFile", treeName, "File already exists, can't create new")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
message := ""
|
||||
if form.CommitSummary != "" {
|
||||
message = strings.Trim(form.CommitSummary, " ")
|
||||
} else {
|
||||
if isNewFile {
|
||||
message = ctx.Tr("repo.add") + " '" + treeName + "'"
|
||||
} else {
|
||||
message = ctx.Tr("repo.update") + " '" + treeName + "'"
|
||||
}
|
||||
}
|
||||
if strings.Trim(form.CommitMessage, " ") != "" {
|
||||
message += "\n\n" + strings.Trim(form.CommitMessage, " ")
|
||||
}
|
||||
|
||||
if err := ctx.Repo.Repository.UpdateRepoFile(ctx.User, oldBranchName, branchName, oldTreeName, treeName, content, message, isNewFile); err != nil {
|
||||
ctx.Data["Err_Filename"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.unable_to_update_file"), EDIT, &form)
|
||||
log.Error(4, "%s: %v", "EditFile", err)
|
||||
return
|
||||
}
|
||||
|
||||
if branch, err := ctx.Repo.Repository.GetBranch(branchName); err != nil {
|
||||
log.Error(4, "repo.Repository.GetBranch(%s): %v", branchName, err)
|
||||
} else if commit, err := branch.GetCommit(); err != nil {
|
||||
log.Error(4, "branch.GetCommit(): %v", err)
|
||||
} else {
|
||||
pc := &models.PushCommits{
|
||||
Len: 1,
|
||||
Commits: []*models.PushCommit{&models.PushCommit{
|
||||
commit.ID.String(),
|
||||
commit.Message(),
|
||||
commit.Author.Email,
|
||||
commit.Author.Name,
|
||||
}},
|
||||
}
|
||||
oldCommitID := ctx.Repo.CommitID
|
||||
newCommitID := commit.ID.String()
|
||||
if branchName != oldBranchName {
|
||||
oldCommitID = "0000000000000000000000000000000000000000" // New Branch so we use all 0s
|
||||
}
|
||||
if err := models.CommitRepoAction(ctx.User.ID, ctx.Repo.Owner.ID, ctx.User.LowerName, ctx.Repo.Owner.Email,
|
||||
ctx.Repo.Repository.ID, ctx.Repo.Owner.LowerName, ctx.Repo.Repository.Name, "refs/heads/"+branchName, pc,
|
||||
oldCommitID, newCommitID); err != nil {
|
||||
log.Error(4, "models.CommitRepoAction(branch = %s): %v", branchName, err)
|
||||
}
|
||||
models.HookQueue.Add(ctx.Repo.Repository.ID)
|
||||
}
|
||||
|
||||
// Leaving this off until forked repos that get a branch can compare with forks master and not upstream
|
||||
//if oldBranchName != branchName {
|
||||
// ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/compare/" + oldBranchName + "..." + branchName))
|
||||
//} else {
|
||||
ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/src/" + branchName + "/" + treeName))
|
||||
//}
|
||||
}
|
||||
|
||||
func DiffPreviewPost(ctx *context.Context, form auth.EditPreviewDiffForm) {
|
||||
userName := ctx.Repo.Owner.Name
|
||||
repoName := ctx.Repo.Repository.Name
|
||||
branchName := ctx.Repo.BranchName
|
||||
treeName := ctx.Repo.TreeName
|
||||
content := form.Content
|
||||
|
||||
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treeName)
|
||||
if (err != nil && git.IsErrNotExist(err)) || entry.IsDir() {
|
||||
ctx.Data["FileContent"] = content
|
||||
ctx.HTML(200, DIFF_PREVIEW_NEW)
|
||||
return
|
||||
}
|
||||
|
||||
diff, err := ctx.Repo.Repository.GetPreviewDiff(models.RepoPath(userName, repoName), branchName, treeName, content, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles)
|
||||
if err != nil {
|
||||
ctx.Error(404, err.Error())
|
||||
log.Error(4, "%s: %v", "GetPreviewDiff", err)
|
||||
return
|
||||
}
|
||||
|
||||
if diff.NumFiles() == 0 {
|
||||
ctx.Error(200, ctx.Tr("repo.no_changes_to_show"))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["IsSplitStyle"] = ctx.Query("style") == "split"
|
||||
ctx.Data["File"] = diff.Files[0]
|
||||
|
||||
ctx.HTML(200, DIFF_PREVIEW)
|
||||
}
|
||||
|
||||
func EscapeUrl(str string) string {
|
||||
return strings.NewReplacer("?", "%3F", "%", "%25", "#", "%23", " ", "%20", "^", "%5E", "\\", "%5C", "{", "%7B", "}", "%7D", "|", "%7C").Replace(str)
|
||||
}
|
||||
@@ -340,6 +340,8 @@ func NewIssue(ctx *context.Context) {
|
||||
}
|
||||
|
||||
ctx.Data["RequireHighlightJS"] = true
|
||||
ctx.Data["RequireSimpleMDE"] = true
|
||||
ctx.Data["RepoName"] = ctx.Repo.Repository.Name
|
||||
|
||||
ctx.HTML(200, ISSUE_NEW)
|
||||
}
|
||||
@@ -401,6 +403,9 @@ func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm) ([]int64
|
||||
func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.issues.new")
|
||||
ctx.Data["PageIsIssueList"] = true
|
||||
ctx.Data["RepoName"] = ctx.Repo.Repository.Name
|
||||
ctx.Data["RequireHighlightJS"] = true
|
||||
ctx.Data["RequireSimpleMDE"] = true
|
||||
renderAttachmentSettings(ctx)
|
||||
|
||||
var (
|
||||
@@ -414,7 +419,7 @@ func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) {
|
||||
}
|
||||
|
||||
if setting.AttachmentEnabled {
|
||||
attachments = form.Attachments
|
||||
attachments = form.Files
|
||||
}
|
||||
|
||||
if ctx.HasError() {
|
||||
@@ -634,6 +639,8 @@ func ViewIssue(ctx *context.Context) {
|
||||
ctx.Data["SignInLink"] = setting.AppSubUrl + "/user/login?redirect_to=" + ctx.Data["Link"].(string)
|
||||
|
||||
ctx.Data["RequireHighlightJS"] = true
|
||||
ctx.Data["RequireSimpleMDE"] = true
|
||||
ctx.Data["RepoName"] = ctx.Repo.Repository.Name
|
||||
|
||||
ctx.HTML(200, ISSUE_VIEW)
|
||||
}
|
||||
@@ -801,7 +808,7 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
||||
|
||||
var attachments []string
|
||||
if setting.AttachmentEnabled {
|
||||
attachments = form.Attachments
|
||||
attachments = form.Files
|
||||
}
|
||||
|
||||
if ctx.HasError() {
|
||||
|
||||
@@ -660,7 +660,7 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm)
|
||||
}
|
||||
|
||||
if setting.AttachmentEnabled {
|
||||
attachments = form.Attachments
|
||||
attachments = form.Files
|
||||
}
|
||||
|
||||
if ctx.HasError() {
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
// Copyright 2016 The Gogs 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 repo
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"fmt"
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
"net/http"
|
||||
"path"
|
||||
)
|
||||
|
||||
const (
|
||||
UPLOAD base.TplName = "repo/upload"
|
||||
)
|
||||
|
||||
func renderUploadSettings(ctx *context.Context) {
|
||||
ctx.Data["RequireDropzone"] = true
|
||||
ctx.Data["IsUploadEnabled"] = setting.UploadEnabled
|
||||
ctx.Data["UploadAllowedTypes"] = setting.UploadAllowedTypes
|
||||
ctx.Data["UploadMaxSize"] = setting.UploadMaxSize
|
||||
ctx.Data["UploadMaxFiles"] = setting.UploadMaxFiles
|
||||
}
|
||||
|
||||
func UploadFile(ctx *context.Context) {
|
||||
ctx.Data["PageIsUpload"] = true
|
||||
|
||||
userName := ctx.Repo.Owner.Name
|
||||
repoName := ctx.Repo.Repository.Name
|
||||
branchName := ctx.Repo.BranchName
|
||||
branchLink := ctx.Repo.RepoLink + "/src/" + branchName
|
||||
treeName := ctx.Repo.TreeName
|
||||
|
||||
treeNames := []string{""}
|
||||
if len(treeName) > 0 {
|
||||
treeNames = strings.Split(treeName, "/")
|
||||
}
|
||||
|
||||
ctx.Data["UserName"] = userName
|
||||
ctx.Data["RepoName"] = repoName
|
||||
ctx.Data["BranchName"] = branchName
|
||||
ctx.Data["TreeName"] = treeName
|
||||
ctx.Data["TreeNames"] = treeNames
|
||||
ctx.Data["BranchLink"] = branchLink
|
||||
ctx.Data["CommitSummary"] = ""
|
||||
ctx.Data["CommitMessage"] = ""
|
||||
ctx.Data["CommitChoice"] = "direct"
|
||||
ctx.Data["NewBranchName"] = ""
|
||||
ctx.Data["CommitDirectlyToThisBranch"] = ctx.Tr("repo.commit_directly_to_this_branch", "<strong class=\"branch-name\">"+branchName+"</strong>")
|
||||
ctx.Data["CreateNewBranch"] = ctx.Tr("repo.create_new_branch", "<strong>"+ctx.Tr("repo.new_branch")+"</strong>")
|
||||
renderUploadSettings(ctx)
|
||||
|
||||
ctx.HTML(200, UPLOAD)
|
||||
}
|
||||
|
||||
func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) {
|
||||
ctx.Data["PageIsUpload"] = true
|
||||
renderUploadSettings(ctx)
|
||||
|
||||
userName := ctx.Repo.Owner.Name
|
||||
repoName := ctx.Repo.Repository.Name
|
||||
oldBranchName := ctx.Repo.BranchName
|
||||
branchName := oldBranchName
|
||||
branchLink := ctx.Repo.RepoLink + "/src/" + branchName
|
||||
commitChoice := form.CommitChoice
|
||||
files := form.Files
|
||||
|
||||
if commitChoice == "commit-to-new-branch" {
|
||||
branchName = form.NewBranchName
|
||||
}
|
||||
|
||||
treeName := form.TreeName
|
||||
treeName = strings.Trim(treeName, " ")
|
||||
treeName = strings.Trim(treeName, "/")
|
||||
|
||||
treeNames := []string{""}
|
||||
if len(treeName) > 0 {
|
||||
treeNames = strings.Split(treeName, "/")
|
||||
}
|
||||
|
||||
ctx.Data["UserName"] = userName
|
||||
ctx.Data["RepoName"] = repoName
|
||||
ctx.Data["BranchName"] = branchName
|
||||
ctx.Data["TreeName"] = treeName
|
||||
ctx.Data["TreeNames"] = treeNames
|
||||
ctx.Data["BranchLink"] = branchLink
|
||||
ctx.Data["CommitSummary"] = form.CommitSummary
|
||||
ctx.Data["CommitMessage"] = form.CommitMessage
|
||||
ctx.Data["CommitChoice"] = commitChoice
|
||||
ctx.Data["NewBranchName"] = branchName
|
||||
ctx.Data["CommitDirectlyToThisBranch"] = ctx.Tr("repo.commit_directly_to_this_branch", "<strong class=\"branch-name\">"+oldBranchName+"</strong>")
|
||||
ctx.Data["CreateNewBranch"] = ctx.Tr("repo.create_new_branch", "<strong>"+ctx.Tr("repo.new_branch")+"</strong>")
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.HTML(200, UPLOAD)
|
||||
return
|
||||
}
|
||||
|
||||
if oldBranchName != branchName {
|
||||
if _, err := ctx.Repo.Repository.GetBranch(branchName); err == nil {
|
||||
ctx.Data["Err_Branchname"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.branch_already_exists"), UPLOAD, &form)
|
||||
log.Error(4, "%s: %s - %s", "BranchName", branchName, "Branch already exists")
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
treepath := ""
|
||||
for _, part := range treeNames {
|
||||
treepath = path.Join(treepath, part)
|
||||
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treepath)
|
||||
if err != nil {
|
||||
// Means there is no item with that name, so we're good
|
||||
break
|
||||
}
|
||||
if !entry.IsDir() {
|
||||
ctx.Data["Err_Filename"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.directory_is_a_file"), UPLOAD, &form)
|
||||
log.Error(4, "%s: %s - %s", "UploadFile", treeName, "Directory given is a file")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
message := ""
|
||||
if form.CommitSummary != "" {
|
||||
message = strings.Trim(form.CommitSummary, " ")
|
||||
} else {
|
||||
message = ctx.Tr("repo.add_files_to_dir", "'"+treeName+"'")
|
||||
}
|
||||
if strings.Trim(form.CommitMessage, " ") != "" {
|
||||
message += "\n\n" + strings.Trim(form.CommitMessage, " ")
|
||||
}
|
||||
|
||||
if err := ctx.Repo.Repository.UploadRepoFiles(ctx.User, oldBranchName, branchName, treeName, message, files); err != nil {
|
||||
ctx.Data["Err_Directory"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.unable_to_upload_files"), UPLOAD, &form)
|
||||
log.Error(4, "%s: %v", "UploadFile", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Was successful, so now need to call models.CommitRepoAction() with the new commitID for webhooks and watchers
|
||||
if branch, err := ctx.Repo.Repository.GetBranch(branchName); err != nil {
|
||||
log.Error(4, "repo.Repository.GetBranch(%s): %v", branchName, err)
|
||||
} else if commit, err := branch.GetCommit(); err != nil {
|
||||
log.Error(4, "branch.GetCommit(): %v", err)
|
||||
} else {
|
||||
pc := &models.PushCommits{
|
||||
Len: 1,
|
||||
Commits: []*models.PushCommit{&models.PushCommit{
|
||||
commit.ID.String(),
|
||||
commit.Message(),
|
||||
commit.Author.Email,
|
||||
commit.Author.Name,
|
||||
}},
|
||||
}
|
||||
oldCommitID := ctx.Repo.CommitID
|
||||
newCommitID := commit.ID.String()
|
||||
if branchName != oldBranchName {
|
||||
oldCommitID = "0000000000000000000000000000000000000000" // New Branch so we use all 0s
|
||||
}
|
||||
if err := models.CommitRepoAction(ctx.User.ID, ctx.Repo.Owner.ID, ctx.User.LowerName, ctx.Repo.Owner.Email,
|
||||
ctx.Repo.Repository.ID, ctx.Repo.Owner.LowerName, ctx.Repo.Repository.Name, "refs/heads/"+branchName, pc,
|
||||
oldCommitID, newCommitID); err != nil {
|
||||
log.Error(4, "models.CommitRepoAction(branch = %s): %v", branchName, err)
|
||||
}
|
||||
models.HookQueue.Add(ctx.Repo.Repository.ID)
|
||||
}
|
||||
|
||||
// Leaving this off until forked repos that get a branch can compare with forks master and not upstream
|
||||
//if oldBranchName != branchName {
|
||||
// ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/compare/" + oldBranchName + "..." + branchName))
|
||||
//} else {
|
||||
ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/src/" + branchName + "/" + treeName))
|
||||
//}
|
||||
}
|
||||
|
||||
func UploadFileToServer(ctx *context.Context) {
|
||||
if !setting.UploadEnabled {
|
||||
ctx.Error(404, "upload is not enabled")
|
||||
return
|
||||
}
|
||||
|
||||
file, header, err := ctx.Req.FormFile("file")
|
||||
if err != nil {
|
||||
ctx.Error(500, fmt.Sprintf("FormFile: %v", err))
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
buf := make([]byte, 1024)
|
||||
n, _ := file.Read(buf)
|
||||
if n > 0 {
|
||||
buf = buf[:n]
|
||||
}
|
||||
fileType := http.DetectContentType(buf)
|
||||
|
||||
if len(setting.UploadAllowedTypes) > 0 {
|
||||
allowedTypes := strings.Split(setting.UploadAllowedTypes, ",")
|
||||
allowed := false
|
||||
for _, t := range allowedTypes {
|
||||
t := strings.Trim(t, " ")
|
||||
if t == "*/*" || t == fileType {
|
||||
allowed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !allowed {
|
||||
ctx.Error(400, ErrFileTypeForbidden.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
up, err := models.NewUpload(header.Filename, buf, file, ctx.User.ID, ctx.Repo.Repository.ID)
|
||||
if err != nil {
|
||||
ctx.Error(500, fmt.Sprintf("NewUpload: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
log.Trace("New file uploaded: %s", up.UUID)
|
||||
ctx.JSON(200, map[string]string{
|
||||
"uuid": up.UUID,
|
||||
})
|
||||
}
|
||||
|
||||
func RemoveUploadFileFromServer(ctx *context.Context, form auth.RemoveUploadFileForm) {
|
||||
if !setting.UploadEnabled {
|
||||
ctx.Error(404, "upload is not enabled")
|
||||
return
|
||||
}
|
||||
|
||||
if len(form.File) == 0 {
|
||||
ctx.Error(404, "invalid params")
|
||||
return
|
||||
}
|
||||
|
||||
uuid := form.File
|
||||
|
||||
if err := models.RemoveUpload(uuid, ctx.User.ID, ctx.Repo.Repository.ID); err != nil {
|
||||
ctx.Error(500, fmt.Sprintf("RemoveUpload: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
log.Trace("Upload file removed: %s", uuid)
|
||||
ctx.JSON(200, map[string]string{
|
||||
"uuid": uuid,
|
||||
})
|
||||
}
|
||||
+42
-1
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
"github.com/gogits/gogs/modules/template"
|
||||
"github.com/gogits/gogs/modules/template/highlight"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -40,6 +41,7 @@ func Home(ctx *context.Context) {
|
||||
ctx.Data["Title"] = title
|
||||
ctx.Data["PageIsViewCode"] = true
|
||||
ctx.Data["RequireHighlightJS"] = true
|
||||
ctx.Data["IsWriter"] = ctx.Repo.IsWriter()
|
||||
|
||||
branchName := ctx.Repo.BranchName
|
||||
userName := ctx.Repo.Owner.Name
|
||||
@@ -49,6 +51,11 @@ func Home(ctx *context.Context) {
|
||||
branchLink := ctx.Repo.RepoLink + "/src/" + branchName
|
||||
treeLink := branchLink
|
||||
rawLink := ctx.Repo.RepoLink + "/raw/" + branchName
|
||||
editLink := ctx.Repo.RepoLink + "/_edit/" + branchName
|
||||
newFileLink := ctx.Repo.RepoLink + "/_new/" + branchName
|
||||
deleteLink := ctx.Repo.RepoLink + "/delete/" + branchName
|
||||
forkLink := setting.AppSubUrl + "/repo/fork/" + strconv.FormatInt(ctx.Repo.Repository.ID, 10)
|
||||
uploadFileLink := ctx.Repo.RepoLink + "/upload/" + branchName
|
||||
|
||||
// Get tree path
|
||||
treename := ctx.Repo.TreeName
|
||||
@@ -104,8 +111,10 @@ func Home(ctx *context.Context) {
|
||||
switch {
|
||||
case isPDFFile:
|
||||
ctx.Data["IsPDFFile"] = true
|
||||
ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.cannot_edit_binary_files")
|
||||
case isImageFile:
|
||||
ctx.Data["IsImageFile"] = true
|
||||
ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.cannot_edit_binary_files")
|
||||
case isTextFile:
|
||||
if blob.Size() >= setting.UI.MaxDisplayFileSize {
|
||||
ctx.Data["IsFileTooLarge"] = true
|
||||
@@ -114,8 +123,10 @@ func Home(ctx *context.Context) {
|
||||
d, _ := ioutil.ReadAll(dataRc)
|
||||
buf = append(buf, d...)
|
||||
readmeExist := markdown.IsMarkdownFile(blob.Name()) || markdown.IsReadmeFile(blob.Name())
|
||||
isMarkdown := readmeExist || markdown.IsMarkdownFile(blob.Name())
|
||||
ctx.Data["ReadmeExist"] = readmeExist
|
||||
if readmeExist {
|
||||
ctx.Data["IsMarkdown"] = isMarkdown
|
||||
if isMarkdown {
|
||||
ctx.Data["FileContent"] = string(markdown.Render(buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas()))
|
||||
} else {
|
||||
// Building code view blocks with line number on server side.
|
||||
@@ -143,6 +154,29 @@ func Home(ctx *context.Context) {
|
||||
ctx.Data["LineNums"] = gotemplate.HTML(output.String())
|
||||
}
|
||||
}
|
||||
if ctx.Repo.IsWriter() && ctx.Repo.IsViewBranch {
|
||||
ctx.Data["FileEditLink"] = editLink + "/" + treename
|
||||
ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.edit_this_file")
|
||||
} else {
|
||||
if !ctx.Repo.IsViewBranch {
|
||||
ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.must_be_on_branch")
|
||||
} else if !ctx.Repo.IsWriter() {
|
||||
ctx.Data["FileEditLink"] = forkLink
|
||||
ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.fork_before_edit")
|
||||
}
|
||||
}
|
||||
default:
|
||||
ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.cannot_edit_binary_files")
|
||||
}
|
||||
if ctx.Repo.IsWriter() && ctx.Repo.IsViewBranch {
|
||||
ctx.Data["FileDeleteLink"] = deleteLink + "/" + treename
|
||||
ctx.Data["FileDeleteLinkTooltip"] = ctx.Tr("repo.delete_this_file")
|
||||
} else {
|
||||
if !ctx.Repo.IsViewBranch {
|
||||
ctx.Data["FileDeleteLinkTooltip"] = ctx.Tr("repo.must_be_on_branch")
|
||||
} else if !ctx.Repo.IsWriter() {
|
||||
ctx.Data["FileDeleteLinkTooltip"] = ctx.Tr("repo.must_be_writer")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -200,6 +234,7 @@ func Home(ctx *context.Context) {
|
||||
buf = append(buf, d...)
|
||||
switch {
|
||||
case markdown.IsMarkdownFile(readmeFile.Name()):
|
||||
ctx.Data["IsMarkdown"] = true
|
||||
buf = markdown.Render(buf, treeLink, ctx.Repo.Repository.ComposeMetas())
|
||||
default:
|
||||
buf = bytes.Replace(buf, []byte("\n"), []byte(`<br>`), -1)
|
||||
@@ -220,6 +255,12 @@ func Home(ctx *context.Context) {
|
||||
}
|
||||
ctx.Data["LastCommit"] = lastCommit
|
||||
ctx.Data["LastCommitUser"] = models.ValidateCommitWithEmail(lastCommit)
|
||||
if ctx.Repo.IsWriter() && ctx.Repo.IsViewBranch {
|
||||
ctx.Data["NewFileLink"] = newFileLink + "/" + treename
|
||||
if setting.UploadEnabled {
|
||||
ctx.Data["UploadFileLink"] = uploadFileLink + "/" + treename
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Data["Username"] = userName
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
{{if .Flash.ErrorMsg}}
|
||||
<div class="ui negative message">
|
||||
<p>{{.Flash.ErrorMsg}}</p>
|
||||
<p>{{.Flash.ErrorMsg | Safe}}</p>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .Flash.SuccessMsg}}
|
||||
<div class="ui positive message">
|
||||
<p>{{.Flash.SuccessMsg}}</p>
|
||||
<p>{{.Flash.SuccessMsg | Safe}}</p>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .Flash.InfoMsg}}
|
||||
<div class="ui info message">
|
||||
<p>{{.Flash.InfoMsg}}</p>
|
||||
<p>{{.Flash.InfoMsg| Safe}}</p>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -24,6 +24,11 @@
|
||||
{{if .RequireSimpleMDE}}
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/plugins/simplemde-1.10.1/simplemde.min.css">
|
||||
<script src="{{AppSubUrl}}/plugins/simplemde-1.10.1/simplemde.min.js"></script>
|
||||
<script src="{{AppSubUrl}}/plugins/codemirror-5.17.0/addon/mode/loadmode.js"></script>
|
||||
<script src="{{AppSubUrl}}/plugins/codemirror-5.17.0/mode/meta.js"></script>
|
||||
<script>
|
||||
CodeMirror.modeURL = "{{AppSubUrl}}/plugins/codemirror-5.17.0/mode/%N/%N.js";
|
||||
</script>
|
||||
{{end}}
|
||||
|
||||
<!-- Stylesheet -->
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="fitted item choose reference">
|
||||
<div class="ui floating filter dropdown" data-no-results="{{.i18n.Tr "repo.pulls.no_results"}}">
|
||||
<div class="ui basic small button">
|
||||
<div id="branch-dropdown" class="ui floating filter dropdown" data-no-results="{{.i18n.Tr "repo.pulls.no_results"}}">
|
||||
<div class="ui basic small button">
|
||||
<span class="text">
|
||||
<i class="octicon octicon-git-branch"></i>
|
||||
{{if .IsViewBranch}}{{.i18n.Tr "repo.branch"}}{{else}}{{.i18n.Tr "repo.tree"}}{{end}}:
|
||||
@@ -31,14 +31,57 @@
|
||||
</div>
|
||||
<div id="branch-list" class="scrolling menu" {{if .IsViewTag}}style="display: none"{{end}}>
|
||||
{{range .Branches}}
|
||||
<div class="item {{if eq $.BranchName .}}selected{{end}}" data-url="{{$.RepoLink}}/{{if $.PageIsCommits}}commits{{else}}src{{end}}/{{EscapePound .}}">{{.}}</div>
|
||||
<div class="item {{if eq $.BranchName .}}selected{{end}}" data-url="{{$.RepoLink}}/{{if $.PageIsCommits}}commits{{else}}src{{end}}/{{EscapePound .}}{{if $.TreeName}}/{{EscapePound $.TreeName}}{{end}}">{{.}}</div>
|
||||
{{end}}
|
||||
{{if .IsWriter}}
|
||||
<a href="javascript:void(0)" id="new-branch-item">
|
||||
<i class="octicon octicon-git-branch"></i>
|
||||
{{.i18n.Tr "repo.create_branch"}}: <span id="branch-name-text"></span>
|
||||
<br/>
|
||||
<span class="description">{{.i18n.Tr "repo.from"}} ‘{{.BranchName}}’</span>
|
||||
<form accept-charset="UTF-8" action="{{.RepoLink}}/branches" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<input type="hidden" name="old_branch_name" value="{{.BranchName}}">
|
||||
<input type="hidden" name="branch_name" id="branch-name" value="">
|
||||
</form>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
<div id="tag-list" class="scrolling menu" {{if not .IsViewTag}}style="display: none"{{end}}>
|
||||
{{range .Tags}}
|
||||
<div class="item {{if eq $.BranchName .}}selected{{end}}" data-url="{{$.RepoLink}}/{{if $.PageIsCommits}}commits{{else}}src{{end}}/{{EscapePound .}}">{{.}}</div>
|
||||
<div class="item {{if eq $.BranchName .}}selected{{end}}" data-url="{{$.RepoLink}}/{{if $.PageIsCommits}}commits{{else}}src{{end}}/{{EscapePound .}}{{if $.TreeName}}/{{EscapePound $.TreeName}}{{end}}">{{.}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if .IsWriter}}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
$('#branch-dropdown #new-branch-item').on('click', function(){
|
||||
$(this).find('form').submit();
|
||||
return true;
|
||||
});
|
||||
$('#branch-dropdown input[name=search]').on('keyup', function(){
|
||||
var query = $(this).val().toLowerCase();
|
||||
if(query.length){
|
||||
var unique = true;
|
||||
$('#branch-dropdown #branch-list .item').each(function(i, item){
|
||||
if($(item).text().toLowerCase() == query){
|
||||
unique = false;
|
||||
}
|
||||
});
|
||||
if(unique){
|
||||
$('#new-branch-item #branch-name-text').text(query);
|
||||
$('#new-branch-item #branch-name').val(query);
|
||||
$('#new-branch-item').css('display', 'block');
|
||||
return;
|
||||
}
|
||||
}
|
||||
$('#new-branch-item').hide();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{{end}}
|
||||
|
||||
@@ -90,8 +90,8 @@
|
||||
<table>
|
||||
<tbody>
|
||||
{{if $.IsSplitStyle}}
|
||||
{{range $j, $section := .Sections}}
|
||||
{{range $k, $line := .Lines}}
|
||||
{{range $j, $section := $file.Sections}}
|
||||
{{range $k, $line := $section.Lines}}
|
||||
<tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}">
|
||||
<td class="lines-num lines-num-old">
|
||||
<span rel="{{if $line.LeftIdx}}diff-{{Sha1 $file.Name}}L{{$line.LeftIdx}}{{end}}">{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}</span>
|
||||
@@ -109,8 +109,8 @@
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{range $j, $section := .Sections}}
|
||||
{{range $k, $line := .Lines}}
|
||||
{{range $j, $section := $file.Sections}}
|
||||
{{range $k, $line := $section.Lines}}
|
||||
<tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}">
|
||||
{{if eq .GetType 4}}
|
||||
<td colspan="2" class="lines-num">
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
{{$highlightClass := .File.GetHighlightClass}}
|
||||
<div class="diff-file-box diff-box file-content" id="diff-{{.Index}}">
|
||||
<div class="ui attached table segment">
|
||||
<div class="file-body file-code code-view code-diff">
|
||||
<table>
|
||||
<tbody>
|
||||
{{range $j, $section := .File.Sections}}
|
||||
{{range $k, $line := $section.Lines}}
|
||||
<tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}">
|
||||
{{if eq .GetType 4}}
|
||||
<td colspan="2" class="lines-num">
|
||||
{{/* {{if gt $j 0}}<span class="fold octicon octicon-fold"></span>{{end}} */}}
|
||||
</td>
|
||||
{{else}}
|
||||
<td class="lines-num lines-num-old">
|
||||
<span rel="{{if $line.LeftIdx}}diff-{{Sha1 $.File.Name}}L{{$line.LeftIdx}}{{end}}">{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}</span>
|
||||
</td>
|
||||
<td class="lines-num lines-num-new">
|
||||
<span rel="{{if $line.RightIdx}}diff-{{Sha1 $.File.Name}}R{{$line.RightIdx}}{{end}}">{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}</span>
|
||||
</td>
|
||||
{{end}}
|
||||
<td class="lines-code">
|
||||
<pre><code class="{{if $highlightClass}}language-{{$highlightClass}}{{else}}nohighlight{{end}}">{{$section.GetComputedInlineDiffFor $line}}</code></pre>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,12 @@
|
||||
<div id="file-content" class="ui attached table segment">
|
||||
<div class="file-view code-view has-emoji">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="lines-num"></td>
|
||||
<td class="lines-code"><pre><code><ol class="linenums">{{.FileContent}}</ol></code></pre></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,97 @@
|
||||
{{template "base/head" .}}
|
||||
<div class="repository file edit">
|
||||
{{template "repo/header" .}}
|
||||
<div class="ui container">
|
||||
{{.branchName}}
|
||||
{{template "base/alert" .}}
|
||||
<form class="ui edit form" action="{{EscapePound $.Link}}" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<input type="hidden" name="last_commit" value="{{.LastCommit}}">
|
||||
<div class="ui secondary menu">
|
||||
<div class="item fitted" style="width:100%;">
|
||||
<div class="ui breadcrumb field{{if .Err_Filename}} error{{end}}">
|
||||
<a class="section" href="{{EscapePound $.BranchLink}}">{{.Repository.Name}}</a>
|
||||
{{ $n := len .TreeNames}}
|
||||
{{ $l := Subtract $n 1}}
|
||||
{{range $i, $v := .TreeNames}}
|
||||
<div class="divider"> / </div>
|
||||
{{if eq $i $l}}
|
||||
<input type="text" id="file-name" value="{{$v}}" placeholder="{{$.i18n.Tr "repo.name_your_file"}}" required> <span class="octicon octicon-info poping up" data-content="{{$.i18n.Tr "repo.filename_help"}}" data-position="bottom center" data-variation="tiny"></span>
|
||||
{{else}}
|
||||
<span class="section"><a href="{{EscapePound $.BranchLink}}/{{EscapePound $v}}">{{$v}}</a></span>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<button class="clipboard-tree-name octicon octicon-clippy poping up" type="button" data-content="{{.i18n.Tr "repo.copy_file_path_to_clipboard"}}" data-position="bottom center" data-variation="tiny inverted"></button>
|
||||
<span class="repo-edit-file-cancel">{{.i18n.Tr "repo.or"}} <a href="{{EscapePound $.BranchLink}}/{{EscapePound $.TreeName}}">{{.i18n.Tr "repo.cancel_lower"}}</a></span>
|
||||
<input type="hidden" id="tree-name" name="tree_name" value="{{.TreeName}}" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui top attached tabular menu" data-write="write" data-preview="preview" data-diff="diff">
|
||||
<a class="active item" data-tab="write"><i class="octicon octicon-code"></i> {{.i18n.Tr "repo.edit_file"}}</a>
|
||||
<a class="item" data-tab="preview" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}" data-preview-apis="{{.PreviewTabApis}}"><i class="octicon octicon-eye"></i> {{.i18n.Tr "repo.release.preview"}}</a>
|
||||
<a class="item" data-tab="diff" data-url="{{.PreviewDiffUrl}}" data-context="{{.BranchLink}}"><i class="octicon octicon-diff"></i> {{.i18n.Tr "repo.preview_changes"}}</a>
|
||||
</div>
|
||||
<div class="ui bottom attached active tab segment" data-tab="write">
|
||||
<textarea id="edit_area" name="content" data-id="repo-{{.Repository.Name}}-{{.TreeName}}"
|
||||
data-url="{{AppSubUrl}}/api/v1/markdown"
|
||||
data-context="{{.RepoLink}}"
|
||||
data-md-file-extensions="{{.MdFileExtensions}}"
|
||||
data-line-wrap-extensions="{{.LineWrapExtensions}}">
|
||||
{{.FileContent}}</textarea required>
|
||||
</div>
|
||||
<div class="ui bottom attached tab segment markdown" data-tab="preview">
|
||||
{{.i18n.Tr "repo.release.loading"}}
|
||||
</div>
|
||||
<div class="ui bottom attached tab segment diff" data-tab="diff">
|
||||
{{.i18n.Tr "repo.release.loading"}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="commit-form-wrapper">
|
||||
<img width="48" height="48" class="ui rounded image commit-form-avatar" src="{{.SignedUser.AvatarLink}}">
|
||||
<div class="commit-form">
|
||||
<h3>{{.i18n.Tr "repo.commit_changes"}}</h3>
|
||||
<div class="field">
|
||||
<input name="commit_summary" placeholder="{{if .IsNewFile}}{{.i18n.Tr "repo.add"}} '{{.TreeName}}/<filename>'{{else}}{{.i18n.Tr "repo.update"}} '{{.TreeName}}'{{end}}" value="{{.CommitSummary}}">
|
||||
</div>
|
||||
<div class="field">
|
||||
<textarea name="commit_message" placeholder="{{.i18n.Tr "repo.default_commit_message"}}">{{.CommitMessage}}</textarea>
|
||||
</div>
|
||||
<div class="quick-pull-choice js-quick-pull-choice ">
|
||||
<dl class="form-group">
|
||||
<dd>
|
||||
<div class="form-checkbox">
|
||||
<label>
|
||||
<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="direct"{{if eq .CommitChoice "direct"}} checked="checked"{{end}}>
|
||||
<i class="octicon octicon-git-commit" height="16" width="14"></i>
|
||||
{{.CommitDirectlyToThisBranch | Safe}}
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-checkbox">
|
||||
<label>
|
||||
<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="commit-to-new-branch"{{if eq .CommitChoice "commit-to-new-branch"}} checked="checked"{{end}}>
|
||||
<i class="octicon octicon-git-pull-request" height="16" width="12"></i>
|
||||
{{.CreateNewBranch | Safe}}
|
||||
</label>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
<div class="quick-pull-branch-name">
|
||||
<div class="new-branch-name-input{{if .Err_Branchname}} error{{end}}">
|
||||
<i class="octicon octicon-git-branch quick-pull-new-branch-icon" height="16" width="10"></i>
|
||||
<input type="text" name="new_branch_name" value="{{.NewBranchName}}" class="form-control input-contrast mr-2 js-quick-pull-new-branch-name" placeholder="New branch name…">
|
||||
<span class="text-muted js-quick-pull-normalization-info"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="ui green button">
|
||||
{{.i18n.Tr "repo.commit_changes"}}
|
||||
</button>
|
||||
<a class="ui button red" href="{{EscapePound $.BranchLink}}/{{EscapePound $.TreeName}}">{{.i18n.Tr "repo.cancel"}}</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
@@ -31,8 +31,20 @@
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{if eq $n 0}}
|
||||
<div class="right fitted item">
|
||||
<div class="right fitted item">
|
||||
<div id="file-buttons" class="ui buttons nowrap">
|
||||
{{if .NewFileLink}}
|
||||
<a href="{{EscapePound .NewFileLink}}" class="ui button nowrap">
|
||||
<i class="plus square outline icon"></i> {{.i18n.Tr "repo.new_file"}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .UploadFileLink}}
|
||||
<a href="{{EscapePound .UploadFileLink}}" class="ui button nowrap">
|
||||
<i class="upload icon"></i> {{.i18n.Tr "repo.upload_file"}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if eq $n 0}}
|
||||
<div class="ui action small input" id="clone-panel">
|
||||
<button class="ui basic clone button" id="repo-clone-https" data-link="{{.CloneLink.HTTPS}}">
|
||||
{{if UseHTTPS}}HTTPS{{else}}HTTP{{end}}
|
||||
@@ -54,8 +66,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{if .IsFile}}
|
||||
{{template "repo/view_file" .}}
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
<a class="item" data-tab="preview" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}">{{.i18n.Tr "repo.release.preview"}}</a>
|
||||
</div>
|
||||
<div class="ui bottom attached active tab segment" data-tab="write">
|
||||
<textarea id="content" name="content" tabindex="4">{{if .IssueTemplate}}{{.IssueTemplate}}{{end}}{{if .PullRequestTemplate}}{{.PullRequestTemplate}}{{end}}</textarea>
|
||||
<textarea id="content" class="edit_area" name="content" tabindex="4" data-id="issue-{{.RepoName}}" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.Repo.RepoLink}}">
|
||||
{{if .IssueTemplate}}{{.IssueTemplate}}{{end}}{{if .PullRequestTemplate}}{{.PullRequestTemplate}}{{end}}</textarea>
|
||||
</div>
|
||||
<div class="ui bottom attached tab segment markdown" data-tab="preview">
|
||||
{{.i18n.Tr "repo.release.loading"}}
|
||||
</div>
|
||||
</div>
|
||||
{{if .IsAttachmentEnabled}}
|
||||
<div class="attachments"></div>
|
||||
<div class="files"></div>
|
||||
<div class="ui basic button dropzone" id="dropzone" data-upload-url="{{AppSubUrl}}/issues/attachments" data-accepts="{{.AttachmentAllowedTypes}}" data-max-file="{{.AttachmentMaxFiles}}" data-max-size="{{.AttachmentMaxSize}}" data-default-message="{{.i18n.Tr "dropzone.default_message"}}" data-invalid-input-type="{{.i18n.Tr "dropzone.invalid_input_type"}}" data-file-too-big="{{.i18n.Tr "dropzone.file_too_big"}}" data-remove-file="{{.i18n.Tr "dropzone.remove_file"}}"></div>
|
||||
{{end}}
|
||||
@@ -0,0 +1,79 @@
|
||||
{{template "base/head" .}}
|
||||
<div class="repository file upload">
|
||||
{{template "repo/header" .}}
|
||||
<div class="ui container">
|
||||
{{.branchName}}
|
||||
{{template "base/alert" .}}
|
||||
<form class="ui comment form" action="{{EscapePound $.Link}}" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<div class="ui secondary menu">
|
||||
<div class="item fitted" style="width:100%;">
|
||||
<div class="ui breadcrumb field{{if .Err_Directory}} error{{end}}">
|
||||
<a class="section" href="{{EscapePound $.BranchLink}}">{{.Repository.Name}}</a>
|
||||
{{ $n := len .TreeNames}}
|
||||
{{ $l := Subtract $n 1}}
|
||||
{{range $i, $v := .TreeNames}}
|
||||
<div class="divider"> / </div>
|
||||
{{if eq $i $l}}
|
||||
<input type="text" id="file-name" value="{{$v}}" placeholder="{{$.i18n.Tr "repo.add_subdir"}}">
|
||||
{{else}}
|
||||
<span class="section"><a href="{{EscapePound $.BranchLink}}/{{EscapePound $v}}">{{$v}}</a></span>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<button class="clipboard-tree-name icon octicon octicon-clippy poping up" type="button" data-content="{{.i18n.Tr "repo.copy_file_path_to_clipboard"}}" data-position="bottom center" data-variation="tiny inverted"></button>
|
||||
<span class="repo-edit-file-cancel">{{.i18n.Tr "repo.or"}} <a href="{{EscapePound $.BranchLink}}/{{EscapePound $.TreeName}}">{{.i18n.Tr "repo.cancel_lower"}}</a></span>
|
||||
<input type="hidden" id="tree-name" name="tree_name" value="{{.TreeName}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field ui upload">
|
||||
<div class="files"></div>
|
||||
<div class="ui basic button dropzone" id="dropzone" data-upload-url="{{.RepoLink}}/upload-file" data-remove-url="{{.RepoLink}}/upload-remove" data-csrf="{{.CsrfToken}}" data-accepts="{{.UploadAllowedTypes}}" data-max-file="{{.UploadMaxFiles}}" data-max-size="{{.UploadMaxSize}}" data-default-message="{{.i18n.Tr "dropzone.default_message"}}" data-invalid-input-type="{{.i18n.Tr "dropzone.invalid_input_type"}}" data-file-too-big="{{.i18n.Tr "dropzone.file_too_big"}}" data-remove-file="{{.i18n.Tr "dropzone.remove_file"}}"></div>
|
||||
</div>
|
||||
<div class="commit-form-wrapper">
|
||||
<img width="48" height="48" class="ui rounded image commit-form-avatar" src="{{.SignedUser.AvatarLink}}">
|
||||
<div class="commit-form">
|
||||
<h3>{{.i18n.Tr "repo.commit_changes"}}</h3>
|
||||
<div class="field">
|
||||
<input name="commit_summary" placeholder="{{.i18n.Tr "repo.add_files_to_dir" .TreeName}}" value="{{.CommitSummary}}">
|
||||
</div>
|
||||
<div class="field">
|
||||
<textarea name="commit_message" placeholder="{{.i18n.Tr "repo.default_commit_message"}}">{{.CommitMessage}}</textarea>
|
||||
</div>
|
||||
<div class="quick-pull-choice js-quick-pull-choice ">
|
||||
<dl class="form-group">
|
||||
<dd>
|
||||
<div class="form-checkbox">
|
||||
<label>
|
||||
<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="direct"{{if eq .CommitChoice "direct"}} checked="checked"{{end}}>
|
||||
<i class="octicon octicon-git-commit" height="16" width="14"></i>
|
||||
{{.CommitDirectlyToThisBranch | Safe}}
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-checkbox">
|
||||
<label>
|
||||
<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="commit-to-new-branch"{{if eq .CommitChoice "commit-to-new-branch"}} checked="checked"{{end}}>
|
||||
<i class="octicon octicon-git-pull-request" height="16" width="12"></i>
|
||||
{{.CreateNewBranch | Safe}}
|
||||
</label>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
<div class="quick-pull-branch-name">
|
||||
<div class="new-branch-name-input{{if .Err_Branchname}} error{{end}}">
|
||||
<i class="octicon octicon-git-branch quick-pull-new-branch-icon" height="16" width="10"></i>
|
||||
<input type="text" name="new_branch_name" value="{{.NewBranchName}}" class="form-control input-contrast mr-2 js-quick-pull-new-branch-name" placeholder="New branch name…">
|
||||
<span class="text-muted js-quick-pull-normalization-info"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="ui green button">
|
||||
{{.i18n.Tr "repo.commit_changes"}}
|
||||
</button>
|
||||
<a class="ui button red" href="{{EscapePound $.BranchLink}}/{{EscapePound $.TreeName}}">{{.i18n.Tr "repo.cancel"}}</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
||||
@@ -12,20 +12,34 @@
|
||||
<strong>{{.FileName}}</strong> <span class="text grey normal">{{FileSize .FileSize}}</span>
|
||||
{{end}}
|
||||
{{if not .ReadmeInList}}
|
||||
<div class="ui right">
|
||||
<div class="ui small grey basic buttons">
|
||||
<div class="ui right file-actions">
|
||||
<div class="ui buttons">
|
||||
{{if not .IsViewCommit}}
|
||||
<a class="ui button" href="{{.RepoLink}}/src/{{.CommitID}}/{{EscapePound .TreeName}}">{{.i18n.Tr "repo.file_permalink"}}</a>
|
||||
{{end}}
|
||||
<a class="ui button" href="{{.RepoLink}}/commits/{{EscapePound .BranchName}}/{{EscapePound .TreeName}}">{{.i18n.Tr "repo.file_history"}}</a>
|
||||
<a class="ui button" href="{{EscapePound .FileLink}}">{{.i18n.Tr "repo.file_raw"}}</a>
|
||||
</div>
|
||||
{{if .FileEditLink}}
|
||||
<a href="{{EscapePound $.FileEditLink}}"><i class="poping up octicon octicon-pencil btn-octicon" data-content="{{.FileEditLinkTooltip}}" data-position="bottom center" data-variation="tiny inverted"></i></a>
|
||||
{{else}}
|
||||
<i class="octicon btn-octicon octicon-pencil poping up disabled" data-content="{{.FileEditLinkTooltip}}" data-position="bottom center" data-variation="tiny inverted"></i>
|
||||
{{end}}
|
||||
{{if .FileDeleteLink}}
|
||||
<form id="delete-file-form" class="ui form inline-form" action="{{EscapePound $.FileDeleteLink}}" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<button onclick="submitDeleteForm()" class="octicon octicon-trashcan btn-octicon btn-octicon-danger poping up" type="button" data-content="{{.FileDeleteLinkTooltip}}" data-position="bottom center" data-variation="tiny inverted"></button>
|
||||
<input type="hidden" id="delete-message" name="commit_message" value="">
|
||||
</form>
|
||||
{{else}}
|
||||
<i class="octicon btn-octicon octicon-trashcan poping up disabled" data-content="{{.FileDeleteLinkTooltip}}" data-position="bottom center" data-variation="tiny inverted"></i>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</h4>
|
||||
<div class="ui attached table segment">
|
||||
<div class="file-view {{if .ReadmeExist}}markdown{{else if .IsFileText}}code-view{{end}} has-emoji">
|
||||
{{if .ReadmeExist}}
|
||||
<div class="file-view {{if .IsMarkdown}}markdown{{else if .IsFileText}}code-view{{end}} has-emoji">
|
||||
{{if .IsMarkdown}}
|
||||
{{if .FileContent}}{{.FileContent | Str2html}}{{end}}
|
||||
{{else if not .IsFileText}}
|
||||
<div class="view-raw ui center">
|
||||
@@ -34,7 +48,7 @@
|
||||
{{else if .IsPDFFile}}
|
||||
<iframe width="100%" height="600px" src="{{AppSubUrl}}/plugins/pdfjs-1.4.20/web/viewer.html?file={{EscapePound .FileLink}}"></iframe>
|
||||
{{else}}
|
||||
<a href="{{EscapePound .FileLink}}" rel="nofollow" class="btn btn-gray btn-radius">{{.i18n.Tr "repo.file_view_raw"}}</a>
|
||||
<a href="{{EscapePound $.FileLink}}" rel="nofollow" class="btn btn-gray btn-radius">{{.i18n.Tr "repo.file_view_raw"}}</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{else if .FileSize}}
|
||||
@@ -54,3 +68,13 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function submitDeleteForm() {
|
||||
var message = prompt("{{.i18n.Tr "repo.delete_confirm_message"}}\n\n{{.i18n.Tr "repo.delete_commit_summary"}}", "Delete '{{.TreeName}}'");
|
||||
if (message != null) {
|
||||
$("#delete-message").val(message);
|
||||
$("#delete-file-form").submit()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -18,7 +18,7 @@
|
||||
<input name="title" value="{{.title}}" autofocus required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<textarea id="edit-area" name="content" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}">{{if .PageIsWikiEdit}}{{.content}}{{else}}{{.i18n.Tr "repo.wiki.welcome"}}{{end}}</textarea required>
|
||||
<textarea id="edit_area" name="content" data-id="wiki-{{.old_title}}" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}">{{if .PageIsWikiEdit}}{{.content}}{{else}}{{.i18n.Tr "repo.wiki.welcome"}}{{end}}</textarea required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<input name="message" placeholder="{{.i18n.Tr "repo.wiki.default_commit_message"}}">
|
||||
|
||||
Reference in new issue
Block a user