Browse Source

Web editor: improve edit file and diff preview

Unknwon 3 years ago
parent
commit
cd89f6c502

+ 13 - 15
conf/locale/locale_en-US.ini

@@ -440,36 +440,34 @@ edit_this_file = Edit this file
440 440
 edit_file = Edit file
441 441
 delete_confirm_message = Are you sure you want to delete this file?
442 442
 delete_commit_message = Write a note about this delete (optional)
443
-file_editing_no_longer_exists = The file you are editing no longer exists in the repository
444
-file_already_exists = A file by that name already exists
445 443
 unable_to_update_file = Unable to update this file, error occurred
446
-add = Add
447
-update = Update
448
-filename_cannot_be_empty = Filename cannot be empty
449
-directory_is_a_file = One of the directories in the path is already a file in this repository
450
-filename_is_a_directory = The filename given is an existing directory in the repository
451 444
 must_be_on_branch = You must be on a branch to make or propose changes to this file
452 445
 must_be_writer = You must have write access to make or propose changes to this file
453 446
 cannot_edit_binary_files = Cannot edit binary files
454 447
 filename_help = To add directory, just type it and press /. To remove a directory, go to the beginning of the field and press backspace.
455 448
 fork_before_edit = You must fork this before editing
456
-branch_already_exists = Branch already exists
457
-create_new_branch = Create a %s for this commit and start a pull request.
458 449
 new_branch = new branch
459
-commit_directly_to_this_branch = Commit directly to the %s branch.
450
+editor.commit_directly_to_this_branch = Commit directly to the <strong class="branch-name">%s</strong> branch.
451
+editor.create_new_branch = Create a <strong>new branch</strong> for this commit and start a pull request.
452
+editor.filename_cannot_be_empty = Filename cannot be empty.
453
+editor.branch_already_exists = Branch '%s' already exists in this repository.
454
+editor.directory_is_a_file = Entry '%s' in the parent path is a file not a directory in this repository.
455
+editor.filename_is_a_directory = The filename '%s' is an existing directory in this repository.
456
+editor.file_editing_no_longer_exists = The file '%s' you are editing no longer exists in the repository.
457
+editor.file_changed_while_editing = File content has been changed since you started editing. <a target="_blank" href="%s">Click here</a> to see what have been changed or <strong>press commit again</strong> to overwrite those changes.
458
+editor.file_already_exists = A file with name '%s' already exists in this repository.
459
+editor.add = Add '%s'
460
+editor.update = Update '%s'
461
+editor.failed_to_upload_files = An error occurred while updating file: %v
462
+editor.no_changes_to_show = There are no changes to show.
460 463
 create_branch = Create branch
461 464
 from = from
462 465
 upload_file = Upload file
463 466
 add_files_to_dir = Add files to %s
464
-unable_to_upload_files = Unable to upload files, an error occurred.
465 467
 add_subdir = Add subdirectory...
466 468
 name_your_file = Name your file...
467
-user_has_committed_since_you_started_editing = %s has committed since you started editing.
468
-see_what_changed = See what changed.
469
-pressing_commit_again_will_overwrite_those_changes = Pressing '%s' again will overwrite those changes.
470 469
 copy_file_path_to_clipboard = Copy file path to clipboard
471 470
 preview_changes = Preview Changes
472
-no_changes_to_show = There are no changes to show.
473 471
 
474 472
 commits.commits = Commits
475 473
 commits.search = Search commits

+ 1 - 1
models/git_diff.go

@@ -434,7 +434,7 @@ func GetDiffRange(repoPath, beforeCommitID, afterCommitID string, maxLines, maxL
434 434
 		return nil, fmt.Errorf("Start: %v", err)
435 435
 	}
436 436
 
437
-	pid := process.Add(fmt.Sprintf("GetDiffRange (%s)", repoPath), cmd)
437
+	pid := process.Add(fmt.Sprintf("GetDiffRange [repo_path: %s]", repoPath), cmd)
438 438
 	defer process.Remove(pid)
439 439
 
440 440
 	diff, err := ParsePatch(maxLines, maxLineCharacteres, maxFiles, stdout)

+ 5 - 10
models/pull.go

@@ -334,6 +334,9 @@ var patchConflicts = []string{
334 334
 // testPatch checks if patch can be merged to base repository without conflit.
335 335
 // FIXME: make a mechanism to clean up stable local copies.
336 336
 func (pr *PullRequest) testPatch() (err error) {
337
+	repoWorkingPool.CheckIn(com.ToStr(pr.BaseRepoID))
338
+	defer repoWorkingPool.CheckOut(com.ToStr(pr.BaseRepoID))
339
+
337 340
 	if pr.BaseRepo == nil {
338 341
 		pr.BaseRepo, err = GetRepositoryByID(pr.BaseRepoID)
339 342
 		if err != nil {
@@ -354,20 +357,12 @@ func (pr *PullRequest) testPatch() (err error) {
354 357
 
355 358
 	log.Trace("PullRequest[%d].testPatch (patchPath): %s", pr.ID, patchPath)
356 359
 
357
-	if err := pr.BaseRepo.UpdateLocalCopy(pr.BaseRepo.DefaultBranch); err != nil {
360
+	if err := pr.BaseRepo.UpdateLocalCopyBranch(pr.BaseBranch); err != nil {
358 361
 		return fmt.Errorf("UpdateLocalCopy: %v", err)
359 362
 	}
360 363
 
361
-	// Checkout base branch.
362
-	_, stderr, err := process.ExecDir(-1, pr.BaseRepo.LocalCopyPath(),
363
-		fmt.Sprintf("PullRequest.Merge (git checkout): %v", pr.BaseRepo.ID),
364
-		"git", "checkout", pr.BaseBranch)
365
-	if err != nil {
366
-		return fmt.Errorf("git checkout: %s", stderr)
367
-	}
368
-
369 364
 	pr.Status = PULL_REQUEST_STATUS_CHECKING
370
-	_, stderr, err = process.ExecDir(-1, pr.BaseRepo.LocalCopyPath(),
365
+	_, stderr, err := process.ExecDir(-1, pr.BaseRepo.LocalCopyPath(),
371 366
 		fmt.Sprintf("testPatch (git apply --check): %d", pr.BaseRepo.ID),
372 367
 		"git", "apply", "--check", patchPath)
373 368
 	if err != nil {

+ 22 - 182
models/repo.go

@@ -437,10 +437,14 @@ func (repo *Repository) DescriptionHtml() template.HTML {
437 437
 }
438 438
 
439 439
 func (repo *Repository) LocalCopyPath() string {
440
-	return path.Join(setting.AppDataPath, "tmp/local", com.ToStr(repo.ID))
440
+	return path.Join(setting.AppDataPath, "tmp/local-rpeo", com.ToStr(repo.ID))
441 441
 }
442 442
 
443
-func updateLocalCopy(repoPath, localPath, branch string) error {
443
+// UpdateLocalCopy pulls latest changes of given branch from repoPath to localPath.
444
+// It creates a new clone if local copy does not exist.
445
+// This function checks out target branch by default, it is safe to assume subsequent
446
+// operations are operating against target branch when caller has confidence for no race condition.
447
+func UpdateLocalCopyBranch(repoPath, localPath, branch string) error {
444 448
 	if !com.IsExist(localPath) {
445 449
 		if err := git.Clone(repoPath, localPath, git.CloneRepoOptions{
446 450
 			Timeout: time.Duration(setting.Git.Timeout.Clone) * time.Second,
@@ -450,13 +454,11 @@ func updateLocalCopy(repoPath, localPath, branch string) error {
450 454
 		}
451 455
 	} else {
452 456
 		if err := git.Checkout(localPath, git.CheckoutOptions{
453
-			Branch:  branch,
454
-			Timeout: time.Duration(setting.Git.Timeout.Pull) * time.Second,
457
+			Branch: branch,
455 458
 		}); err != nil {
456 459
 			return fmt.Errorf("Checkout: %v", err)
457 460
 		}
458 461
 		if err := git.Pull(localPath, git.PullRemoteOptions{
459
-			All:     false,
460 462
 			Remote:  "origin",
461 463
 			Branch:  branch,
462 464
 			Timeout: time.Duration(setting.Git.Timeout.Pull) * time.Second,
@@ -467,9 +469,9 @@ func updateLocalCopy(repoPath, localPath, branch string) error {
467 469
 	return nil
468 470
 }
469 471
 
470
-// UpdateLocalCopy makes sure the local copy of repository is up-to-date.
471
-func (repo *Repository) UpdateLocalCopy(branch string) error {
472
-	return updateLocalCopy(repo.RepoPath(), repo.LocalCopyPath(), branch)
472
+// UpdateLocalCopy makes sure the branch of local copy of repository is up-to-date.
473
+func (repo *Repository) UpdateLocalCopyBranch(branch string) error {
474
+	return UpdateLocalCopyBranch(repo.RepoPath(), repo.LocalCopyPath(), branch)
473 475
 }
474 476
 
475 477
 // PatchPath returns corresponding patch file path of repository by given issue ID.
@@ -2238,168 +2240,6 @@ func (repo *Repository) GetForks() ([]*Repository, error) {
2238 2240
 	return forks, x.Find(&forks, &Repository{ForkID: repo.ID})
2239 2241
 }
2240 2242
 
2241
-// ___________    .___.__  __    ___________.__.__
2242
-// \_   _____/  __| _/|__|/  |_  \_   _____/|__|  |   ____
2243
-//  |    __)_  / __ | |  \   __\  |    __)  |  |  | _/ __ \
2244
-//  |        \/ /_/ | |  ||  |    |     \   |  |  |_\  ___/
2245
-// /_______  /\____ | |__||__|    \___  /   |__|____/\___  >
2246
-//         \/      \/                 \/                 \/
2247
-
2248
-func (repo *Repository) LocalRepoPath() string {
2249
-	return path.Join(setting.AppDataPath, "tmp/local-repo", com.ToStr(repo.ID))
2250
-}
2251
-
2252
-// UpdateLocalRepo makes sure the local copy of repository is up-to-date.
2253
-func (repo *Repository) UpdateLocalRepo(branchName string) error {
2254
-	return updateLocalCopy(repo.RepoPath(), repo.LocalRepoPath(), branchName)
2255
-}
2256
-
2257
-// DiscardLocalRepoChanges makes sure the local copy of repository is the same as the source
2258
-func (repo *Repository) DiscardLocalRepoChanges(branchName string) error {
2259
-	return discardLocalRepoChanges(repo.LocalRepoPath(), branchName)
2260
-}
2261
-
2262
-// discardLocalRepoChanges discards local commits make sure
2263
-// it is even to remote branch when local copy exists.
2264
-func discardLocalRepoChanges(localPath string, branch string) error {
2265
-	if !com.IsExist(localPath) {
2266
-		return nil
2267
-	}
2268
-	// No need to check if nothing in the repository.
2269
-	if !git.IsBranchExist(localPath, branch) {
2270
-		return nil
2271
-	}
2272
-	if err := git.ResetHEAD(localPath, true, "origin/"+branch); err != nil {
2273
-		return fmt.Errorf("ResetHEAD: %v", err)
2274
-	}
2275
-	return nil
2276
-}
2277
-
2278
-// CheckoutNewBranch checks out a new branch from the given branch name
2279
-func (repo *Repository) CheckoutNewBranch(oldBranchName, newBranchName string) error {
2280
-	return checkoutNewBranch(repo.RepoPath(), repo.LocalRepoPath(), oldBranchName, newBranchName)
2281
-}
2282
-
2283
-func checkoutNewBranch(repoPath, localPath, oldBranch, newBranch string) error {
2284
-	if !com.IsExist(localPath) {
2285
-		if err := updateLocalCopy(repoPath, localPath, oldBranch); err != nil {
2286
-			return err
2287
-		}
2288
-	}
2289
-	if err := git.Checkout(localPath, git.CheckoutOptions{
2290
-		Branch:    newBranch,
2291
-		OldBranch: oldBranch,
2292
-		Timeout:   time.Duration(setting.Git.Timeout.Pull) * time.Second,
2293
-	}); err != nil {
2294
-		return fmt.Errorf("Checkout New Branch: %v", err)
2295
-	}
2296
-	return nil
2297
-}
2298
-
2299
-// updateRepoFile adds new file to repository.
2300
-func (repo *Repository) UpdateRepoFile(doer *User, oldBranchName, branchName, oldTreeName, treeName, content, message string, isNewFile bool) (err error) {
2301
-	repoWorkingPool.CheckIn(com.ToStr(repo.ID))
2302
-	defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
2303
-
2304
-	if err = repo.DiscardLocalRepoChanges(oldBranchName); err != nil {
2305
-		return fmt.Errorf("discardLocalRepoChanges: %s - %v", oldBranchName, err)
2306
-	} else if err = repo.UpdateLocalRepo(oldBranchName); err != nil {
2307
-		return fmt.Errorf("UpdateLocalRepo: %s - %v", oldBranchName, err)
2308
-	}
2309
-
2310
-	if oldBranchName != branchName {
2311
-		if err := repo.CheckoutNewBranch(oldBranchName, branchName); err != nil {
2312
-			return fmt.Errorf("CheckoutNewBranch: %s - %s: %v", oldBranchName, branchName, err)
2313
-		}
2314
-	}
2315
-
2316
-	localPath := repo.LocalRepoPath()
2317
-	filePath := path.Join(localPath, treeName)
2318
-
2319
-	if len(message) == 0 {
2320
-		if isNewFile {
2321
-			message = "Add '" + treeName + "'"
2322
-		} else {
2323
-			message = "Update '" + treeName + "'"
2324
-		}
2325
-	}
2326
-
2327
-	os.MkdirAll(filepath.Dir(filePath), os.ModePerm)
2328
-
2329
-	// If new file, make sure it doesn't exist; if old file, move if file name change
2330
-	if isNewFile {
2331
-		if com.IsExist(filePath) {
2332
-			return ErrRepoFileAlreadyExist{filePath}
2333
-		}
2334
-	} else if oldTreeName != "" && treeName != "" && treeName != oldTreeName {
2335
-		if err = git.MoveFile(localPath, oldTreeName, treeName); err != nil {
2336
-			return fmt.Errorf("MoveFile: %v", err)
2337
-		}
2338
-	}
2339
-
2340
-	if err = ioutil.WriteFile(filePath, []byte(content), 0666); err != nil {
2341
-		return fmt.Errorf("WriteFile: %v", err)
2342
-	}
2343
-
2344
-	if err = git.AddChanges(localPath, true); err != nil {
2345
-		return fmt.Errorf("AddChanges: %v", err)
2346
-	} else if err = git.CommitChanges(localPath, message, doer.NewGitSig()); err != nil {
2347
-		return fmt.Errorf("CommitChanges: %v", err)
2348
-	} else if err = git.Push(localPath, "origin", branchName); err != nil {
2349
-		return fmt.Errorf("Push: %v", err)
2350
-	}
2351
-
2352
-	return nil
2353
-}
2354
-
2355
-func (repo *Repository) GetPreviewDiff(repoPath, branchName, treeName, text string, maxlines, maxchars, maxfiles int) (diff *Diff, err error) {
2356
-	repoWorkingPool.CheckIn(com.ToStr(repo.ID))
2357
-	defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
2358
-
2359
-	if err = repo.DiscardLocalRepoChanges(branchName); err != nil {
2360
-		return nil, fmt.Errorf("discardLocalRepoChanges: %s - %v", branchName, err)
2361
-	} else if err = repo.UpdateLocalRepo(branchName); err != nil {
2362
-		return nil, fmt.Errorf("UpdateLocalRepo: %s - %v", branchName, err)
2363
-	}
2364
-
2365
-	localPath := repo.LocalRepoPath()
2366
-	filePath := path.Join(localPath, treeName)
2367
-
2368
-	os.MkdirAll(filepath.Dir(filePath), os.ModePerm)
2369
-
2370
-	if err = ioutil.WriteFile(filePath, []byte(text), 0666); err != nil {
2371
-		return nil, fmt.Errorf("WriteFile: %v", err)
2372
-	}
2373
-
2374
-	var cmd *exec.Cmd
2375
-	cmd = exec.Command("git", "diff", treeName)
2376
-	cmd.Dir = localPath
2377
-	cmd.Stderr = os.Stderr
2378
-
2379
-	stdout, err := cmd.StdoutPipe()
2380
-	if err != nil {
2381
-		return nil, fmt.Errorf("StdoutPipe: %v", err)
2382
-	}
2383
-
2384
-	if err = cmd.Start(); err != nil {
2385
-		return nil, fmt.Errorf("Start: %v", err)
2386
-	}
2387
-
2388
-	pid := process.Add(fmt.Sprintf("GetDiffRange (%s)", repoPath), cmd)
2389
-	defer process.Remove(pid)
2390
-
2391
-	diff, err = ParsePatch(maxlines, maxchars, maxfiles, stdout)
2392
-	if err != nil {
2393
-		return nil, fmt.Errorf("ParsePatch: %v", err)
2394
-	}
2395
-
2396
-	if err = cmd.Wait(); err != nil {
2397
-		return nil, fmt.Errorf("Wait: %v", err)
2398
-	}
2399
-
2400
-	return diff, nil
2401
-}
2402
-
2403 2243
 // ________         .__          __           ___________.__.__
2404 2244
 // \______ \   ____ |  |   _____/  |_  ____   \_   _____/|__|  |   ____
2405 2245
 //  |    |  \_/ __ \|  | _/ __ \   __\/ __ \   |    __)  |  |  | _/ __ \
@@ -2412,11 +2252,11 @@ func (repo *Repository) DeleteRepoFile(doer *User, branch, treeName, message str
2412 2252
 	repoWorkingPool.CheckIn(com.ToStr(repo.ID))
2413 2253
 	defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
2414 2254
 
2415
-	localPath := repo.LocalRepoPath()
2416
-	if err = discardLocalRepoChanges(localPath, branch); err != nil {
2255
+	localPath := repo.LocalCopyPath()
2256
+	if err = discardLocalRepoBranchChanges(localPath, branch); err != nil {
2417 2257
 		return fmt.Errorf("discardLocalRepoChanges: %v", err)
2418
-	} else if err = repo.UpdateLocalRepo(branch); err != nil {
2419
-		return fmt.Errorf("UpdateLocalRepo: %v", err)
2258
+	} else if err = repo.UpdateLocalCopyBranch(branch); err != nil {
2259
+		return fmt.Errorf("UpdateLocalCopyBranch: %v", err)
2420 2260
 	}
2421 2261
 
2422 2262
 	filePath := path.Join(localPath, treeName)
@@ -2450,12 +2290,12 @@ func (repo *Repository) UploadRepoFiles(doer *User, oldBranchName, branchName, t
2450 2290
 	repoWorkingPool.CheckIn(com.ToStr(repo.ID))
2451 2291
 	defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
2452 2292
 
2453
-	localPath := repo.LocalRepoPath()
2293
+	localPath := repo.LocalCopyPath()
2454 2294
 
2455
-	if err = discardLocalRepoChanges(localPath, oldBranchName); err != nil {
2295
+	if err = discardLocalRepoBranchChanges(localPath, oldBranchName); err != nil {
2456 2296
 		return fmt.Errorf("discardLocalRepoChanges: %v", err)
2457
-	} else if err = repo.UpdateLocalRepo(oldBranchName); err != nil {
2458
-		return fmt.Errorf("UpdateLocalRepo: %v", err)
2297
+	} else if err = repo.UpdateLocalCopyBranch(oldBranchName); err != nil {
2298
+		return fmt.Errorf("UpdateLocalCopyBranch: %v", err)
2459 2299
 	}
2460 2300
 
2461 2301
 	if oldBranchName != branchName {
@@ -2637,12 +2477,12 @@ func (repo *Repository) CreateNewBranch(doer *User, oldBranchName, branchName st
2637 2477
 	repoWorkingPool.CheckIn(com.ToStr(repo.ID))
2638 2478
 	defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
2639 2479
 
2640
-	localPath := repo.LocalRepoPath()
2480
+	localPath := repo.LocalCopyPath()
2641 2481
 
2642
-	if err = discardLocalRepoChanges(localPath, oldBranchName); err != nil {
2482
+	if err = discardLocalRepoBranchChanges(localPath, oldBranchName); err != nil {
2643 2483
 		return fmt.Errorf("discardLocalRepoChanges: %v", err)
2644
-	} else if err = repo.UpdateLocalRepo(oldBranchName); err != nil {
2645
-		return fmt.Errorf("UpdateLocalRepo: %v", err)
2484
+	} else if err = repo.UpdateLocalCopyBranch(oldBranchName); err != nil {
2485
+		return fmt.Errorf("UpdateLocalCopyBranch: %v", err)
2646 2486
 	}
2647 2487
 
2648 2488
 	if err = repo.CheckoutNewBranch(oldBranchName, branchName); err != nil {

+ 211 - 0
models/repo_editor.go

@@ -0,0 +1,211 @@
1
+// Copyright 2016 The Gogs Authors. All rights reserved.
2
+// Use of this source code is governed by a MIT-style
3
+// license that can be found in the LICENSE file.
4
+
5
+package models
6
+
7
+import (
8
+	"fmt"
9
+	"io/ioutil"
10
+	"os"
11
+	"os/exec"
12
+	"path"
13
+	"path/filepath"
14
+	"time"
15
+
16
+	"github.com/Unknwon/com"
17
+
18
+	git "github.com/gogits/git-module"
19
+
20
+	"github.com/gogits/gogs/modules/log"
21
+	"github.com/gogits/gogs/modules/process"
22
+	"github.com/gogits/gogs/modules/setting"
23
+)
24
+
25
+// ___________    .___.__  __    ___________.__.__
26
+// \_   _____/  __| _/|__|/  |_  \_   _____/|__|  |   ____
27
+//  |    __)_  / __ | |  \   __\  |    __)  |  |  | _/ __ \
28
+//  |        \/ /_/ | |  ||  |    |     \   |  |  |_\  ___/
29
+// /_______  /\____ | |__||__|    \___  /   |__|____/\___  >
30
+//         \/      \/                 \/                 \/
31
+
32
+// discardLocalRepoBranchChanges discards local commits of given branch
33
+// to make sure it is even to remote branch when local copy exists.
34
+func discardLocalRepoBranchChanges(localPath, branch string) error {
35
+	if !com.IsExist(localPath) {
36
+		return nil
37
+	}
38
+	// No need to check if nothing in the repository.
39
+	if !git.IsBranchExist(localPath, branch) {
40
+		return nil
41
+	}
42
+	if err := git.ResetHEAD(localPath, true, "origin/"+branch); err != nil {
43
+		return fmt.Errorf("ResetHEAD: %v", err)
44
+	}
45
+	return nil
46
+}
47
+
48
+func (repo *Repository) DiscardLocalRepoBranchChanges(branch string) error {
49
+	return discardLocalRepoBranchChanges(repo.LocalCopyPath(), branch)
50
+}
51
+
52
+func checkoutNewBranch(repoPath, localPath, oldBranch, newBranch string) error {
53
+	if !com.IsExist(localPath) {
54
+		if err := UpdateLocalCopyBranch(repoPath, localPath, oldBranch); err != nil {
55
+			return err
56
+		}
57
+	}
58
+	if err := git.Checkout(localPath, git.CheckoutOptions{
59
+		Branch:    newBranch,
60
+		OldBranch: oldBranch,
61
+		Timeout:   time.Duration(setting.Git.Timeout.Pull) * time.Second,
62
+	}); err != nil {
63
+		return fmt.Errorf("Checkout: %v", err)
64
+	}
65
+	return nil
66
+}
67
+
68
+// CheckoutNewBranch checks out a new branch from the given branch name.
69
+func (repo *Repository) CheckoutNewBranch(oldBranch, newBranch string) error {
70
+	return checkoutNewBranch(repo.RepoPath(), repo.LocalCopyPath(), oldBranch, newBranch)
71
+}
72
+
73
+type UpdateRepoFileOptions struct {
74
+	LastCommitID string
75
+	OldBranch    string
76
+	NewBranch    string
77
+	OldTreeName  string
78
+	NewTreeName  string
79
+	Message      string
80
+	Content      string
81
+	IsNewFile    bool
82
+}
83
+
84
+// updateRepoFile adds new file to repository.
85
+func (repo *Repository) UpdateRepoFile(doer *User, opts *UpdateRepoFileOptions) (err error) {
86
+	repoWorkingPool.CheckIn(com.ToStr(repo.ID))
87
+	defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
88
+
89
+	if err = repo.DiscardLocalRepoBranchChanges(opts.OldBranch); err != nil {
90
+		return fmt.Errorf("DiscardLocalRepoBranchChanges [branch: %s]: %v", opts.OldBranch, err)
91
+	} else if err = repo.UpdateLocalCopyBranch(opts.OldBranch); err != nil {
92
+		return fmt.Errorf("UpdateLocalCopyBranch [branch: %s]: %v", opts.OldBranch, err)
93
+	}
94
+
95
+	if opts.OldBranch != opts.NewBranch {
96
+		if err := repo.CheckoutNewBranch(opts.OldBranch, opts.NewBranch); err != nil {
97
+			return fmt.Errorf("CheckoutNewBranch [old_branch: %s, new_branch: %s]: %v", opts.OldBranch, opts.NewBranch, err)
98
+		}
99
+	}
100
+
101
+	localPath := repo.LocalCopyPath()
102
+	filePath := path.Join(localPath, opts.NewTreeName)
103
+
104
+	if len(opts.Message) == 0 {
105
+		if opts.IsNewFile {
106
+			opts.Message = "Add '" + opts.NewTreeName + "'"
107
+		} else {
108
+			opts.Message = "Update '" + opts.NewTreeName + "'"
109
+		}
110
+	}
111
+
112
+	os.MkdirAll(path.Dir(filePath), os.ModePerm)
113
+
114
+	// If new file, make sure it doesn't exist; if old file, move if file name change.
115
+	if opts.IsNewFile {
116
+		if com.IsExist(filePath) {
117
+			return ErrRepoFileAlreadyExist{filePath}
118
+		}
119
+	} else if len(opts.OldTreeName) > 0 && len(opts.NewTreeName) > 0 && opts.NewTreeName != opts.OldTreeName {
120
+		if err = git.MoveFile(localPath, opts.OldTreeName, opts.NewTreeName); err != nil {
121
+			return fmt.Errorf("MoveFile [old_tree_name: %s, new_tree_name: %s]: %v", opts.OldTreeName, opts.NewTreeName, err)
122
+		}
123
+	}
124
+
125
+	if err = ioutil.WriteFile(filePath, []byte(opts.Content), 0666); err != nil {
126
+		return fmt.Errorf("WriteFile: %v", err)
127
+	}
128
+
129
+	if err = git.AddChanges(localPath, true); err != nil {
130
+		return fmt.Errorf("AddChanges: %v", err)
131
+	} else if err = git.CommitChanges(localPath, opts.Message, doer.NewGitSig()); err != nil {
132
+		return fmt.Errorf("CommitChanges: %v", err)
133
+	} else if err = git.Push(localPath, "origin", opts.NewBranch); err != nil {
134
+		return fmt.Errorf("Push: %v", err)
135
+	}
136
+
137
+	gitRepo, err := git.OpenRepository(repo.RepoPath())
138
+	if err != nil {
139
+		log.Error(4, "OpenRepository: %v", err)
140
+		return nil
141
+	}
142
+	commit, err := gitRepo.GetBranchCommit(opts.NewBranch)
143
+	if err != nil {
144
+		log.Error(4, "GetBranchCommit [branch: %s]: %v", opts.NewBranch, err)
145
+		return nil
146
+	}
147
+
148
+	pushCommits := &PushCommits{
149
+		Len:     1,
150
+		Commits: []*PushCommit{CommitToPushCommit(commit)},
151
+	}
152
+	oldCommitID := opts.LastCommitID
153
+	if opts.NewBranch != opts.OldBranch {
154
+		oldCommitID = "0000000000000000000000000000000000000000" // New Branch so we use all 0s
155
+	}
156
+	if err := CommitRepoAction(doer.ID, repo.MustOwner().ID, doer.Name, doer.Email,
157
+		repo.ID, repo.MustOwner().Name, repo.Name, git.BRANCH_PREFIX+opts.NewBranch,
158
+		pushCommits, oldCommitID, commit.ID.String()); err != nil {
159
+		log.Error(4, "CommitRepoAction: %v", err)
160
+		return nil
161
+	}
162
+	go HookQueue.Add(repo.ID)
163
+
164
+	return nil
165
+}
166
+
167
+func (repo *Repository) GetDiffPreview(branch, treeName, content string) (diff *Diff, err error) {
168
+	repoWorkingPool.CheckIn(com.ToStr(repo.ID))
169
+	defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
170
+
171
+	if err = repo.DiscardLocalRepoBranchChanges(branch); err != nil {
172
+		return nil, fmt.Errorf("discardLocalRepoChanges: %s - %v", branch, err)
173
+	} else if err = repo.UpdateLocalCopyBranch(branch); err != nil {
174
+		return nil, fmt.Errorf("UpdateLocalCopyBranch: %s - %v", branch, err)
175
+	}
176
+
177
+	localPath := repo.LocalCopyPath()
178
+	filePath := path.Join(localPath, treeName)
179
+
180
+	os.MkdirAll(filepath.Dir(filePath), os.ModePerm)
181
+	if err = ioutil.WriteFile(filePath, []byte(content), 0666); err != nil {
182
+		return nil, fmt.Errorf("WriteFile: %v", err)
183
+	}
184
+
185
+	cmd := exec.Command("git", "diff", treeName)
186
+	cmd.Dir = localPath
187
+	cmd.Stderr = os.Stderr
188
+
189
+	stdout, err := cmd.StdoutPipe()
190
+	if err != nil {
191
+		return nil, fmt.Errorf("StdoutPipe: %v", err)
192
+	}
193
+
194
+	if err = cmd.Start(); err != nil {
195
+		return nil, fmt.Errorf("Start: %v", err)
196
+	}
197
+
198
+	pid := process.Add(fmt.Sprintf("GetDiffRange [repo_path: %s]", repo.RepoPath()), cmd)
199
+	defer process.Remove(pid)
200
+
201
+	diff, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, stdout)
202
+	if err != nil {
203
+		return nil, fmt.Errorf("ParsePatch: %v", err)
204
+	}
205
+
206
+	if err = cmd.Wait(); err != nil {
207
+		return nil, fmt.Errorf("Wait: %v", err)
208
+	}
209
+
210
+	return diff, nil
211
+}

+ 2 - 15
models/wiki.go

@@ -76,24 +76,11 @@ func (repo *Repository) LocalWikiPath() string {
76 76
 
77 77
 // UpdateLocalWiki makes sure the local copy of repository wiki is up-to-date.
78 78
 func (repo *Repository) UpdateLocalWiki() error {
79
-	return updateLocalCopy(repo.WikiPath(), repo.LocalWikiPath(), "")
79
+	return UpdateLocalCopyBranch(repo.WikiPath(), repo.LocalWikiPath(), "master")
80 80
 }
81 81
 
82
-// discardLocalWikiChanges discards local commits make sure
83
-// it is even to remote branch when local copy exists.
84 82
 func discardLocalWikiChanges(localPath string) error {
85
-	if !com.IsExist(localPath) {
86
-		return nil
87
-	}
88
-	// No need to check if nothing in the repository.
89
-	if !git.IsBranchExist(localPath, "master") {
90
-		return nil
91
-	}
92
-
93
-	if err := git.ResetHEAD(localPath, true, "origin/master"); err != nil {
94
-		return fmt.Errorf("ResetHEAD: %v", err)
95
-	}
96
-	return nil
83
+	return discardLocalRepoBranchChanges(localPath, "master")
97 84
 }
98 85
 
99 86
 // updateWikiPage adds new page to repository wiki.

File diff suppressed because it is too large
+ 3 - 3
modules/bindata/bindata.go


+ 3 - 3
routers/repo/branch.go

@@ -40,14 +40,14 @@ func NewBranchPost(ctx *context.Context, form auth.NewBranchForm) {
40 40
 	branchName := form.BranchName
41 41
 
42 42
 	if ctx.HasError() || !ctx.Repo.IsWriter() || branchName == oldBranchName {
43
-		ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/src/" + oldBranchName))
43
+		ctx.Redirect(ctx.Repo.RepoLink + "/src/" + oldBranchName)
44 44
 		return
45 45
 	}
46 46
 
47 47
 	branchName = url.QueryEscape(strings.Replace(strings.Trim(branchName, " "), " ", "-", -1))
48 48
 
49 49
 	if _, err := ctx.Repo.Repository.GetBranch(branchName); err == nil {
50
-		ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/src/" + branchName))
50
+		ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName)
51 51
 		return
52 52
 	}
53 53
 
@@ -77,5 +77,5 @@ func NewBranchPost(ctx *context.Context, form auth.NewBranchForm) {
77 77
 		models.HookQueue.Add(ctx.Repo.Repository.ID)
78 78
 	}
79 79
 
80
-	ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/src/" + branchName))
80
+	ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName)
81 81
 }

+ 120 - 145
routers/repo/edit.go

@@ -20,28 +20,24 @@ import (
20 20
 )
21 21
 
22 22
 const (
23
-	EDIT             base.TplName = "repo/edit"
24
-	DIFF_PREVIEW     base.TplName = "repo/diff_preview"
25
-	DIFF_PREVIEW_NEW base.TplName = "repo/diff_preview_new"
23
+	EDIT             base.TplName = "repo/editor/edit"
24
+	DIFF_PREVIEW     base.TplName = "repo/editor/diff_preview"
25
+	DIFF_PREVIEW_NEW base.TplName = "repo/editor/diff_preview_new"
26 26
 )
27 27
 
28
-func EditFile(ctx *context.Context) {
29
-	editFile(ctx, false)
30
-}
31
-
32
-func NewFile(ctx *context.Context) {
33
-	editFile(ctx, true)
34
-}
35
-
36 28
 func editFile(ctx *context.Context, isNewFile bool) {
29
+	// Don't allow edit a file in a specific commit.
30
+	if ctx.Repo.IsViewCommit {
31
+		ctx.Handle(404, "", nil)
32
+		return
33
+	}
34
+
37 35
 	ctx.Data["PageIsEdit"] = true
38 36
 	ctx.Data["IsNewFile"] = isNewFile
39 37
 	ctx.Data["RequireHighlightJS"] = true
38
+	ctx.Data["RequireSimpleMDE"] = true
40 39
 
41
-	userName := ctx.Repo.Owner.Name
42
-	repoName := ctx.Repo.Repository.Name
43
-	branchName := ctx.Repo.BranchName
44
-	branchLink := ctx.Repo.RepoLink + "/src/" + branchName
40
+	branchLink := ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchName
45 41
 	treeName := ctx.Repo.TreeName
46 42
 
47 43
 	var treeNames []string
@@ -51,19 +47,22 @@ func editFile(ctx *context.Context, isNewFile bool) {
51 47
 
52 48
 	if !isNewFile {
53 49
 		entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treeName)
54
-
55
-		if err != nil && git.IsErrNotExist(err) {
56
-			ctx.Handle(404, "GetTreeEntryByPath", err)
50
+		if err != nil {
51
+			if git.IsErrNotExist(err) {
52
+				ctx.Handle(404, "GetTreeEntryByPath", err)
53
+			} else {
54
+				ctx.Handle(500, "GetTreeEntryByPath", err)
55
+			}
57 56
 			return
58 57
 		}
59 58
 
60
-		if (ctx.Repo.IsViewCommit) || entry == nil || entry.IsDir() {
61
-			ctx.Handle(404, "repo.Home", nil)
59
+		// No way to edit a directory online.
60
+		if entry.IsDir() {
61
+			ctx.Handle(404, "", nil)
62 62
 			return
63 63
 		}
64 64
 
65 65
 		blob := entry.Blob()
66
-
67 66
 		dataRc, err := blob.Data()
68 67
 		if err != nil {
69 68
 			ctx.Handle(404, "blob.Data", err)
@@ -79,16 +78,15 @@ func editFile(ctx *context.Context, isNewFile bool) {
79 78
 			buf = buf[:n]
80 79
 		}
81 80
 
81
+		// Only text file are editable online.
82 82
 		_, isTextFile := base.IsTextFile(buf)
83
-
84 83
 		if !isTextFile {
85
-			ctx.Handle(404, "repo.Home", nil)
84
+			ctx.Handle(404, "", nil)
86 85
 			return
87 86
 		}
88 87
 
89 88
 		d, _ := ioutil.ReadAll(dataRc)
90 89
 		buf = append(buf, d...)
91
-
92 90
 		if err, content := template.ToUTF8WithErr(buf); err != nil {
93 91
 			if err != nil {
94 92
 				log.Error(4, "Convert content encoding: %s", err)
@@ -98,47 +96,38 @@ func editFile(ctx *context.Context, isNewFile bool) {
98 96
 			ctx.Data["FileContent"] = content
99 97
 		}
100 98
 	} else {
101
-		treeNames = append(treeNames, "")
99
+		treeNames = append(treeNames, "") // Append empty string to allow user name the new file.
102 100
 	}
103 101
 
104
-	ctx.Data["RequireSimpleMDE"] = true
105
-
106
-	ctx.Data["UserName"] = userName
107
-	ctx.Data["RepoName"] = repoName
108
-	ctx.Data["BranchName"] = branchName
109 102
 	ctx.Data["TreeName"] = treeName
110 103
 	ctx.Data["TreeNames"] = treeNames
111 104
 	ctx.Data["BranchLink"] = branchLink
112
-	ctx.Data["CommitSummary"] = ""
113
-	ctx.Data["CommitMessage"] = ""
114
-	ctx.Data["CommitChoice"] = "direct"
115
-	ctx.Data["NewBranchName"] = ""
116
-	ctx.Data["CommitDirectlyToThisBranch"] = ctx.Tr("repo.commit_directly_to_this_branch", "<strong class=\"branch-name\">"+branchName+"</strong>")
117
-	ctx.Data["CreateNewBranch"] = ctx.Tr("repo.create_new_branch", "<strong>"+ctx.Tr("repo.new_branch")+"</strong>")
118
-	ctx.Data["LastCommit"] = ctx.Repo.Commit.ID
105
+	ctx.Data["commit_summary"] = ""
106
+	ctx.Data["commit_message"] = ""
107
+	ctx.Data["commit_choice"] = "direct"
108
+	ctx.Data["new_branch_name"] = ""
109
+	ctx.Data["last_commit"] = ctx.Repo.Commit.ID
119 110
 	ctx.Data["MarkdownFileExts"] = strings.Join(setting.Markdown.FileExtensions, ",")
120 111
 	ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
121 112
 	ctx.Data["PreviewableFileModes"] = strings.Join(setting.Repository.Editor.PreviewableFileModes, ",")
122
-	ctx.Data["PreviewDiffURL"] = ctx.Repo.RepoLink + "/preview/" + branchName + "/" + treeName
123 113
 
124 114
 	ctx.HTML(200, EDIT)
125 115
 }
126 116
 
127
-func EditFilePost(ctx *context.Context, form auth.EditRepoFileForm) {
128
-	editFilePost(ctx, form, false)
117
+func EditFile(ctx *context.Context) {
118
+	editFile(ctx, false)
129 119
 }
130 120
 
131
-func NewFilePost(ctx *context.Context, form auth.EditRepoFileForm) {
132
-	editFilePost(ctx, form, true)
121
+func NewFile(ctx *context.Context) {
122
+	editFile(ctx, true)
133 123
 }
134 124
 
135 125
 func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bool) {
136 126
 	ctx.Data["PageIsEdit"] = true
137 127
 	ctx.Data["IsNewFile"] = isNewFile
138 128
 	ctx.Data["RequireHighlightJS"] = true
129
+	ctx.Data["RequireSimpleMDE"] = true
139 130
 
140
-	userName := ctx.Repo.Owner.Name
141
-	repoName := ctx.Repo.Repository.Name
142 131
 	oldBranchName := ctx.Repo.BranchName
143 132
 	branchName := oldBranchName
144 133
 	branchLink := ctx.Repo.RepoLink + "/src/" + branchName
@@ -160,26 +149,18 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
160 149
 		treeNames = strings.Split(treeName, "/")
161 150
 	}
162 151
 
163
-	ctx.Data["RequireSimpleMDE"] = true
164
-
165
-	ctx.Data["UserName"] = userName
166
-	ctx.Data["RepoName"] = repoName
167
-	ctx.Data["BranchName"] = branchName
168 152
 	ctx.Data["TreeName"] = treeName
169 153
 	ctx.Data["TreeNames"] = treeNames
170 154
 	ctx.Data["BranchLink"] = branchLink
171 155
 	ctx.Data["FileContent"] = content
172
-	ctx.Data["CommitSummary"] = form.CommitSummary
173
-	ctx.Data["CommitMessage"] = form.CommitMessage
174
-	ctx.Data["CommitChoice"] = commitChoice
175
-	ctx.Data["NewBranchName"] = branchName
176
-	ctx.Data["CommitDirectlyToThisBranch"] = ctx.Tr("repo.commit_directly_to_this_branch", "<strong class=\"branch-name\">"+oldBranchName+"</strong>")
177
-	ctx.Data["CreateNewBranch"] = ctx.Tr("repo.create_new_branch", "<strong>"+ctx.Tr("repo.new_branch")+"</strong>")
178
-	ctx.Data["LastCommit"] = ctx.Repo.Commit.ID
156
+	ctx.Data["commit_summary"] = form.CommitSummary
157
+	ctx.Data["commit_message"] = form.CommitMessage
158
+	ctx.Data["commit_choice"] = commitChoice
159
+	ctx.Data["new_branch_name"] = branchName
160
+	ctx.Data["last_commit"] = ctx.Repo.Commit.ID
179 161
 	ctx.Data["MarkdownFileExts"] = strings.Join(setting.Markdown.FileExtensions, ",")
180 162
 	ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
181 163
 	ctx.Data["PreviewableFileModes"] = strings.Join(setting.Repository.Editor.PreviewableFileModes, ",")
182
-	ctx.Data["PreviewDiffURL"] = ctx.Repo.RepoLink + "/preview/" + branchName + "/" + treeName
183 164
 
184 165
 	if ctx.HasError() {
185 166
 		ctx.HTML(200, EDIT)
@@ -188,41 +169,41 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
188 169
 
189 170
 	if len(treeName) == 0 {
190 171
 		ctx.Data["Err_Filename"] = true
191
-		ctx.RenderWithErr(ctx.Tr("repo.filename_cannot_be_empty"), EDIT, &form)
192
-		log.Error(4, "%s: %s", "EditFile", "Filename can't be empty")
172
+		ctx.RenderWithErr(ctx.Tr("repo.editor.filename_cannot_be_empty"), EDIT, &form)
193 173
 		return
194 174
 	}
195 175
 
196 176
 	if oldBranchName != branchName {
197 177
 		if _, err := ctx.Repo.Repository.GetBranch(branchName); err == nil {
198 178
 			ctx.Data["Err_Branchname"] = true
199
-			ctx.RenderWithErr(ctx.Tr("repo.branch_already_exists"), EDIT, &form)
200
-			log.Error(4, "%s: %s - %s", "BranchName", branchName, "Branch already exists")
179
+			ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchName), EDIT, &form)
201 180
 			return
202 181
 		}
203
-
204 182
 	}
205 183
 
206
-	treepath := ""
184
+	var treepath string
207 185
 	for index, part := range treeNames {
208 186
 		treepath = path.Join(treepath, part)
209 187
 		entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treepath)
210 188
 		if err != nil {
211
-			// Means there is no item with that name, so we're good
212
-			break
189
+			if git.IsErrNotExist(err) {
190
+				// Means there is no item with that name, so we're good
191
+				break
192
+			}
193
+
194
+			ctx.Handle(500, "GetTreeEntryByPath", err)
195
+			return
213 196
 		}
214 197
 		if index != len(treeNames)-1 {
215 198
 			if !entry.IsDir() {
216 199
 				ctx.Data["Err_Filename"] = true
217
-				ctx.RenderWithErr(ctx.Tr("repo.directory_is_a_file"), EDIT, &form)
218
-				log.Error(4, "%s: %s - %s", "EditFile", treeName, "Directory given is a file")
200
+				ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", part), EDIT, &form)
219 201
 				return
220 202
 			}
221 203
 		} else {
222 204
 			if entry.IsDir() {
223 205
 				ctx.Data["Err_Filename"] = true
224
-				ctx.RenderWithErr(ctx.Tr("repo.filename_is_a_directory"), EDIT, &form)
225
-				log.Error(4, "%s: %s - %s", "EditFile", treeName, "Filename given is a dirctory")
206
+				ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_a_directory", part), EDIT, &form)
226 207
 				return
227 208
 			}
228 209
 		}
@@ -230,125 +211,119 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
230 211
 
231 212
 	if !isNewFile {
232 213
 		_, err := ctx.Repo.Commit.GetTreeEntryByPath(oldTreeName)
233
-		if err != nil && git.IsErrNotExist(err) {
234
-			ctx.Data["Err_Filename"] = true
235
-			ctx.RenderWithErr(ctx.Tr("repo.file_editing_no_longer_exists"), EDIT, &form)
236
-			log.Error(4, "%s: %s / %s - %s", "EditFile", branchName, oldTreeName, "File doesn't exist for editing")
214
+		if err != nil {
215
+			if git.IsErrNotExist(err) {
216
+				ctx.Data["Err_Filename"] = true
217
+				ctx.RenderWithErr(ctx.Tr("repo.editor.file_editing_no_longer_exists", oldTreeName), EDIT, &form)
218
+			} else {
219
+				ctx.Handle(500, "GetTreeEntryByPath", err)
220
+			}
237 221
 			return
238 222
 		}
239 223
 		if lastCommit != ctx.Repo.CommitID {
240
-			if files, err := ctx.Repo.Commit.GetFilesChangedSinceCommit(lastCommit); err == nil {
241
-				for _, file := range files {
242
-					if file == treeName {
243
-						name := ctx.Repo.Commit.Author.Name
244
-						if u, err := models.GetUserByEmail(ctx.Repo.Commit.Author.Email); err == nil {
245
-							name = `<a href="` + setting.AppSubUrl + "/" + u.Name + `" target="_blank">` + u.Name + `</a>`
246
-						}
247
-						message := ctx.Tr("repo.user_has_committed_since_you_started_editing", name) +
248
-							` <a href="` + ctx.Repo.RepoLink + "/commit/" + ctx.Repo.CommitID + `" target="_blank">` + ctx.Tr("repo.see_what_changed") + `</a>` +
249
-							" " + ctx.Tr("repo.pressing_commit_again_will_overwrite_those_changes", "<em>"+ctx.Tr("repo.commit_changes")+"</em>")
250
-						log.Error(4, "%s: %s / %s - %s", "EditFile", branchName, oldTreeName, "File updated by another user")
251
-						ctx.RenderWithErr(message, EDIT, &form)
252
-						return
253
-					}
224
+			files, err := ctx.Repo.Commit.GetFilesChangedSinceCommit(lastCommit)
225
+			if err != nil {
226
+				ctx.Handle(500, "GetFilesChangedSinceCommit", err)
227
+				return
228
+			}
229
+
230
+			for _, file := range files {
231
+				if file == treeName {
232
+					ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+lastCommit+"..."+ctx.Repo.CommitID), EDIT, &form)
233
+					return
254 234
 				}
255 235
 			}
256 236
 		}
257 237
 	}
238
+
258 239
 	if oldTreeName != treeName {
259
-		// We have a new filename (rename or completely new file) so we need to make sure it doesn't already exist, can't clobber
260
-		_, err := ctx.Repo.Commit.GetTreeEntryByPath(treeName)
261
-		if err == nil {
240
+		// We have a new filename (rename or completely new file) so we need to make sure it doesn't already exist, can't clobber.
241
+		entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treeName)
242
+		if err != nil {
243
+			if !git.IsErrNotExist(err) {
244
+				ctx.Handle(500, "GetTreeEntryByPath", err)
245
+				return
246
+			}
247
+		}
248
+		if entry != nil {
262 249
 			ctx.Data["Err_Filename"] = true
263
-			ctx.RenderWithErr(ctx.Tr("repo.file_already_exists"), EDIT, &form)
264
-			log.Error(4, "%s: %s - %s", "NewFile", treeName, "File already exists, can't create new")
250
+			ctx.RenderWithErr(ctx.Tr("repo.editor.file_already_exists", treeName), EDIT, &form)
265 251
 			return
266 252
 		}
267 253
 	}
268 254
 
269
-	message := ""
270
-	if form.CommitSummary != "" {
271
-		message = strings.Trim(form.CommitSummary, " ")
255
+	var message string
256
+	if len(form.CommitSummary) > 0 {
257
+		message = strings.TrimSpace(form.CommitSummary)
272 258
 	} else {
273 259
 		if isNewFile {
274
-			message = ctx.Tr("repo.add") + " '" + treeName + "'"
260
+			message = ctx.Tr("repo.editor.add", treeName)
275 261
 		} else {
276
-			message = ctx.Tr("repo.update") + " '" + treeName + "'"
262
+			message = ctx.Tr("repo.editor.update", treeName)
277 263
 		}
278 264
 	}
279
-	if strings.Trim(form.CommitMessage, " ") != "" {
280
-		message += "\n\n" + strings.Trim(form.CommitMessage, " ")
265
+
266
+	form.CommitMessage = strings.TrimSpace(form.CommitMessage)
267
+	if len(form.CommitMessage) > 0 {
268
+		message += "\n\n" + form.CommitMessage
281 269
 	}
282 270
 
283
-	if err := ctx.Repo.Repository.UpdateRepoFile(ctx.User, oldBranchName, branchName, oldTreeName, treeName, content, message, isNewFile); err != nil {
271
+	if err := ctx.Repo.Repository.UpdateRepoFile(ctx.User, &models.UpdateRepoFileOptions{
272
+		LastCommitID: lastCommit,
273
+		OldBranch:    oldBranchName,
274
+		NewBranch:    branchName,
275
+		OldTreeName:  oldTreeName,
276
+		NewTreeName:  treeName,
277
+		Message:      message,
278
+		Content:      content,
279
+		IsNewFile:    isNewFile,
280
+	}); err != nil {
284 281
 		ctx.Data["Err_Filename"] = true
285
-		ctx.RenderWithErr(ctx.Tr("repo.unable_to_update_file"), EDIT, &form)
286
-		log.Error(4, "%s: %v", "EditFile", err)
282
+		ctx.RenderWithErr(ctx.Tr("repo.editor.failed_to_update_file", err), EDIT, &form)
287 283
 		return
288 284
 	}
289 285
 
290
-	if branch, err := ctx.Repo.Repository.GetBranch(branchName); err != nil {
291
-		log.Error(4, "repo.Repository.GetBranch(%s): %v", branchName, err)
292
-	} else if commit, err := branch.GetCommit(); err != nil {
293
-		log.Error(4, "branch.GetCommit(): %v", err)
294
-	} else {
295
-		pc := &models.PushCommits{
296
-			Len:     1,
297
-			Commits: []*models.PushCommit{models.CommitToPushCommit(commit)},
298
-		}
299
-		oldCommitID := ctx.Repo.CommitID
300
-		newCommitID := commit.ID.String()
301
-		if branchName != oldBranchName {
302
-			oldCommitID = "0000000000000000000000000000000000000000" // New Branch so we use all 0s
303
-		}
304
-		if err := models.CommitRepoAction(ctx.User.ID, ctx.Repo.Owner.ID, ctx.User.LowerName, ctx.Repo.Owner.Email,
305
-			ctx.Repo.Repository.ID, ctx.Repo.Owner.LowerName, ctx.Repo.Repository.Name, "refs/heads/"+branchName, pc,
306
-			oldCommitID, newCommitID); err != nil {
307
-			log.Error(4, "models.CommitRepoAction(branch = %s): %v", branchName, err)
308
-		}
309
-		models.HookQueue.Add(ctx.Repo.Repository.ID)
310
-	}
286
+	ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName + "/" + treeName)
287
+}
311 288
 
312
-	// Leaving this off until forked repos that get a branch can compare with forks master and not upstream
313
-	//if oldBranchName != branchName {
314
-	//	ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/compare/" + oldBranchName + "..." + branchName))
315
-	//} else {
316
-	ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/src/" + branchName + "/" + treeName))
317
-	//}
289
+func EditFilePost(ctx *context.Context, form auth.EditRepoFileForm) {
290
+	editFilePost(ctx, form, false)
291
+}
292
+
293
+func NewFilePost(ctx *context.Context, form auth.EditRepoFileForm) {
294
+	editFilePost(ctx, form, true)
318 295
 }
319 296
 
320 297
 func DiffPreviewPost(ctx *context.Context, form auth.EditPreviewDiffForm) {
321
-	userName := ctx.Repo.Owner.Name
322
-	repoName := ctx.Repo.Repository.Name
323
-	branchName := ctx.Repo.BranchName
324 298
 	treeName := ctx.Repo.TreeName
325 299
 	content := form.Content
326 300
 
327 301
 	entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treeName)
328
-	if (err != nil && git.IsErrNotExist(err)) || entry.IsDir() {
329
-		ctx.Data["FileContent"] = content
330
-		ctx.HTML(200, DIFF_PREVIEW_NEW)
302
+	if err != nil {
303
+		if git.IsErrNotExist(err) {
304
+			ctx.Data["FileContent"] = content
305
+			ctx.HTML(200, DIFF_PREVIEW_NEW)
306
+		} else {
307
+			ctx.Error(500, "GetTreeEntryByPath: "+err.Error())
308
+		}
309
+		return
310
+	}
311
+	if entry.IsDir() {
312
+		ctx.Error(422)
331 313
 		return
332 314
 	}
333 315
 
334
-	diff, err := ctx.Repo.Repository.GetPreviewDiff(models.RepoPath(userName, repoName), branchName, treeName, content, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles)
316
+	diff, err := ctx.Repo.Repository.GetDiffPreview(ctx.Repo.BranchName, treeName, content)
335 317
 	if err != nil {
336
-		ctx.Error(404, err.Error())
337
-		log.Error(4, "%s: %v", "GetPreviewDiff", err)
318
+		ctx.Error(500, "GetDiffPreview: "+err.Error())
338 319
 		return
339 320
 	}
340 321
 
341 322
 	if diff.NumFiles() == 0 {
342
-		ctx.Error(200, ctx.Tr("repo.no_changes_to_show"))
323
+		ctx.PlainText(200, []byte(ctx.Tr("repo.editor.no_changes_to_show")))
343 324
 		return
344 325
 	}
345
-
346
-	ctx.Data["IsSplitStyle"] = ctx.Query("style") == "split"
347 326
 	ctx.Data["File"] = diff.Files[0]
348 327
 
349 328
 	ctx.HTML(200, DIFF_PREVIEW)
350 329
 }
351
-
352
-func EscapeUrl(str string) string {
353
-	return strings.NewReplacer("?", "%3F", "%", "%25", "#", "%23", " ", "%20", "^", "%5E", "\\", "%5C", "{", "%7B", "}", "%7D", "|", "%7C").Replace(str)
354
-}

+ 1 - 6
routers/repo/upload.go

@@ -170,12 +170,7 @@ func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) {
170 170
 		models.HookQueue.Add(ctx.Repo.Repository.ID)
171 171
 	}
172 172
 
173
-	// Leaving this off until forked repos that get a branch can compare with forks master and not upstream
174
-	//if oldBranchName != branchName {
175
-	//	ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/compare/" + oldBranchName + "..." + branchName))
176
-	//} else {
177
-	ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/src/" + branchName + "/" + treeName))
178
-	//}
173
+	ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName + "/" + treeName)
179 174
 }
180 175
 
181 176
 func UploadFileToServer(ctx *context.Context) {

+ 85 - 83
routers/repo/view.go

@@ -75,110 +75,112 @@ func Home(ctx *context.Context) {
75 75
 	}
76 76
 
77 77
 	entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treename)
78
-	if err != nil && git.IsErrNotExist(err) {
79
-		ctx.Handle(404, "GetTreeEntryByPath", err)
78
+	if err != nil {
79
+		if git.IsErrNotExist(err) {
80
+			ctx.Handle(404, "GetTreeEntryByPath", err)
81
+		} else {
82
+			ctx.Handle(500, "GetTreeEntryByPath", err)
83
+		}
80 84
 		return
81 85
 	}
82 86
 
83
-	if len(treename) != 0 && entry == nil {
84
-		ctx.Handle(404, "repo.Home", nil)
85
-		return
86
-	}
87
-	if entry != nil && !entry.IsDir() {
87
+	if !entry.IsDir() {
88 88
 		blob := entry.Blob()
89
-
90
-		if dataRc, err := blob.Data(); err != nil {
89
+		dataRc, err := blob.Data()
90
+		if err != nil {
91 91
 			ctx.Handle(404, "blob.Data", err)
92 92
 			return
93
-		} else {
94
-			ctx.Data["FileSize"] = blob.Size()
95
-			ctx.Data["IsFile"] = true
96
-			ctx.Data["FileName"] = blob.Name()
97
-			ctx.Data["HighlightClass"] = highlight.FileNameToHighlightClass(blob.Name())
98
-			ctx.Data["FileLink"] = rawLink + "/" + treename
99
-
100
-			buf := make([]byte, 1024)
101
-			n, _ := dataRc.Read(buf)
102
-			if n > 0 {
103
-				buf = buf[:n]
104
-			}
93
+		}
105 94
 
106
-			_, isTextFile := base.IsTextFile(buf)
107
-			_, isImageFile := base.IsImageFile(buf)
108
-			_, isPDFFile := base.IsPDFFile(buf)
109
-			ctx.Data["IsFileText"] = isTextFile
110
-
111
-			switch {
112
-			case isPDFFile:
113
-				ctx.Data["IsPDFFile"] = true
114
-				ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.cannot_edit_binary_files")
115
-			case isImageFile:
116
-				ctx.Data["IsImageFile"] = true
117
-				ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.cannot_edit_binary_files")
118
-			case isTextFile:
119
-				if blob.Size() >= setting.UI.MaxDisplayFileSize {
120
-					ctx.Data["IsFileTooLarge"] = true
121
-				} else {
122
-					ctx.Data["IsFileTooLarge"] = false
123
-					d, _ := ioutil.ReadAll(dataRc)
124
-					buf = append(buf, d...)
125
-					readmeExist := markdown.IsMarkdownFile(blob.Name()) || markdown.IsReadmeFile(blob.Name())
126
-					isMarkdown := readmeExist || markdown.IsMarkdownFile(blob.Name())
127
-					ctx.Data["ReadmeExist"] = readmeExist
128
-					ctx.Data["IsMarkdown"] = isMarkdown
129
-					if isMarkdown {
130
-						ctx.Data["FileContent"] = string(markdown.Render(buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas()))
131
-					} else {
132
-						// Building code view blocks with line number on server side.
133
-						var filecontent string
134
-						if err, content := template.ToUTF8WithErr(buf); err != nil {
135
-							if err != nil {
136
-								log.Error(4, "ToUTF8WithErr: %s", err)
137
-							}
138
-							filecontent = string(buf)
139
-						} else {
140
-							filecontent = content
141
-						}
95
+		ctx.Data["FileSize"] = blob.Size()
96
+		ctx.Data["IsFile"] = true
97
+		ctx.Data["FileName"] = blob.Name()
98
+		ctx.Data["HighlightClass"] = highlight.FileNameToHighlightClass(blob.Name())
99
+		ctx.Data["FileLink"] = rawLink + "/" + treename
142 100
 
143
-						var output bytes.Buffer
144
-						lines := strings.Split(filecontent, "\n")
145
-						for index, line := range lines {
146
-							output.WriteString(fmt.Sprintf(`<li class="L%d" rel="L%d">%s</li>`, index+1, index+1, gotemplate.HTMLEscapeString(line)) + "\n")
147
-						}
148
-						ctx.Data["FileContent"] = gotemplate.HTML(output.String())
101
+		buf := make([]byte, 1024)
102
+		n, _ := dataRc.Read(buf)
103
+		if n > 0 {
104
+			buf = buf[:n]
105
+		}
149 106
 
150
-						output.Reset()
151
-						for i := 0; i < len(lines); i++ {
152
-							output.WriteString(fmt.Sprintf(`<span id="L%d">%d</span>`, i+1, i+1))
107
+		_, isTextFile := base.IsTextFile(buf)
108
+		_, isImageFile := base.IsImageFile(buf)
109
+		_, isPDFFile := base.IsPDFFile(buf)
110
+		ctx.Data["IsFileText"] = isTextFile
111
+
112
+		switch {
113
+		case isPDFFile:
114
+			ctx.Data["IsPDFFile"] = true
115
+			ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.cannot_edit_binary_files")
116
+		case isImageFile:
117
+			ctx.Data["IsImageFile"] = true
118
+			ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.cannot_edit_binary_files")
119
+		case isTextFile:
120
+			if blob.Size() >= setting.UI.MaxDisplayFileSize {
121
+				ctx.Data["IsFileTooLarge"] = true
122
+			} else {
123
+				ctx.Data["IsFileTooLarge"] = false
124
+				d, _ := ioutil.ReadAll(dataRc)
125
+				buf = append(buf, d...)
126
+				readmeExist := markdown.IsMarkdownFile(blob.Name()) || markdown.IsReadmeFile(blob.Name())
127
+				isMarkdown := readmeExist || markdown.IsMarkdownFile(blob.Name())
128
+				ctx.Data["ReadmeExist"] = readmeExist
129
+				ctx.Data["IsMarkdown"] = isMarkdown
130
+				if isMarkdown {
131
+					ctx.Data["FileContent"] = string(markdown.Render(buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas()))
132
+				} else {
133
+					// Building code view blocks with line number on server side.
134
+					var filecontent string
135
+					if err, content := template.ToUTF8WithErr(buf); err != nil {
136
+						if err != nil {
137
+							log.Error(4, "ToUTF8WithErr: %s", err)
153 138
 						}
154
-						ctx.Data["LineNums"] = gotemplate.HTML(output.String())
139
+						filecontent = string(buf)
140
+					} else {
141
+						filecontent = content
155 142
 					}
156
-				}
157
-				if ctx.Repo.IsWriter() && ctx.Repo.IsViewBranch {
158
-					ctx.Data["FileEditLink"] = editLink + "/" + treename
159
-					ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.edit_this_file")
160
-				} else {
161
-					if !ctx.Repo.IsViewBranch {
162
-						ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.must_be_on_branch")
163
-					} else if !ctx.Repo.IsWriter() {
164
-						ctx.Data["FileEditLink"] = forkLink
165
-						ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.fork_before_edit")
143
+
144
+					var output bytes.Buffer
145
+					lines := strings.Split(filecontent, "\n")
146
+					for index, line := range lines {
147
+						output.WriteString(fmt.Sprintf(`<li class="L%d" rel="L%d">%s</li>`, index+1, index+1, gotemplate.HTMLEscapeString(line)) + "\n")
166 148
 					}
149
+					ctx.Data["FileContent"] = gotemplate.HTML(output.String())
150
+
151
+					output.Reset()
152
+					for i := 0; i < len(lines); i++ {
153
+						output.WriteString(fmt.Sprintf(`<span id="L%d">%d</span>`, i+1, i+1))
154
+					}
155
+					ctx.Data["LineNums"] = gotemplate.HTML(output.String())
167 156
 				}
168
-			default:
169
-				ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.cannot_edit_binary_files")
170 157
 			}
171 158
 			if ctx.Repo.IsWriter() && ctx.Repo.IsViewBranch {
172
-				ctx.Data["FileDeleteLink"] = deleteLink + "/" + treename
173
-				ctx.Data["FileDeleteLinkTooltip"] = ctx.Tr("repo.delete_this_file")
159
+				ctx.Data["FileEditLink"] = editLink + "/" + treename
160
+				ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.edit_this_file")
174 161
 			} else {
175 162
 				if !ctx.Repo.IsViewBranch {
176
-					ctx.Data["FileDeleteLinkTooltip"] = ctx.Tr("repo.must_be_on_branch")
163
+					ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.must_be_on_branch")
177 164
 				} else if !ctx.Repo.IsWriter() {
178
-					ctx.Data["FileDeleteLinkTooltip"] = ctx.Tr("repo.must_be_writer")
165
+					ctx.Data["FileEditLink"] = forkLink
166
+					ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.fork_before_edit")
179 167
 				}
180 168
 			}
169
+		default:
170
+			ctx.Data["FileEditLinkTooltip"] = ctx.Tr("repo.cannot_edit_binary_files")
181 171
 		}
172
+
173
+		if ctx.Repo.IsWriter() && ctx.Repo.IsViewBranch {
174
+			ctx.Data["FileDeleteLink"] = deleteLink + "/" + treename
175
+			ctx.Data["FileDeleteLinkTooltip"] = ctx.Tr("repo.delete_this_file")
176
+		} else {
177
+			if !ctx.Repo.IsViewBranch {
178
+				ctx.Data["FileDeleteLinkTooltip"] = ctx.Tr("repo.must_be_on_branch")
179
+			} else if !ctx.Repo.IsWriter() {
180
+				ctx.Data["FileDeleteLinkTooltip"] = ctx.Tr("repo.must_be_writer")
181
+			}
182
+		}
183
+
182 184
 	} else {
183 185
 		// Directory and file list.
184 186
 		tree, err := ctx.Repo.Commit.SubTree(treename)

+ 2 - 2
templates/repo/diff_box.tmpl

@@ -71,9 +71,9 @@
71 71
 					{{if not $file.IsSubmodule}}
72 72
 						<div class="ui right">
73 73
 							{{if $file.IsDeleted}}
74
-								<a class="ui basic tiny button" rel="nofollow" href="{{EscapePound $.BeforeSourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
74
+								<a class="ui basic grey tiny button" rel="nofollow" href="{{EscapePound $.BeforeSourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
75 75
 							{{else}}
76
-								<a class="ui basic tiny button" rel="nofollow" href="{{EscapePound $.SourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
76
+								<a class="ui basic grey tiny button" rel="nofollow" href="{{EscapePound $.SourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
77 77
 							{{end}}
78 78
 						</div>
79 79
 					{{end}}

templates/repo/diff_preview.tmpl → templates/repo/editor/diff_preview.tmpl


templates/repo/diff_preview_new.tmpl → templates/repo/editor/diff_preview_new.tmpl


+ 10 - 11
templates/repo/edit.tmpl

@@ -2,11 +2,10 @@
2 2
 <div class="repository file edit">
3 3
 	{{template "repo/header" .}}
4 4
 	<div class="ui container">
5
-		{{.branchName}}
6 5
 		{{template "base/alert" .}}
7 6
 		<form class="ui edit form" action="{{EscapePound $.Link}}" method="post">
8 7
 			{{.CsrfTokenHtml}}
9
-			<input type="hidden" name="last_commit" value="{{.LastCommit}}">
8
+			<input type="hidden" name="last_commit" value="{{.last_commit}}">
10 9
 			<div class="ui secondary menu">
11 10
 				<div class="item fitted" style="width:100%;">
12 11
 					<div class="ui breadcrumb field{{if .Err_Filename}} error{{end}}">
@@ -31,7 +30,7 @@
31 30
 				<div class="ui top attached tabular menu" data-write="write" data-preview="preview" data-diff="diff">
32 31
 					<a class="active item" data-tab="write"><i class="octicon octicon-code"></i> {{.i18n.Tr "repo.edit_file"}}</a>
33 32
 					<a class="item" data-tab="preview" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}" data-preview-file-modes="{{.PreviewableFileModes}}"><i class="octicon octicon-eye"></i> {{.i18n.Tr "repo.release.preview"}}</a>
34
-					<a class="item" data-tab="diff" data-url="{{.PreviewDiffURL}}" data-context="{{.BranchLink}}"><i class="octicon octicon-diff"></i> {{.i18n.Tr "repo.preview_changes"}}</a>
33
+					<a class="item" data-tab="diff" data-url="{{.RepoLink}}/preview/{{.BranchName}}/{{.TreeName}}" data-context="{{.BranchLink}}"><i class="octicon octicon-diff"></i> {{.i18n.Tr "repo.preview_changes"}}</a>
35 34
 				</div>
36 35
 				<div class="ui bottom attached active tab segment" data-tab="write">
37 36
 					<textarea id="edit_area" name="content" data-id="repo-{{.Repository.Name}}-{{.TreeName}}"
@@ -53,26 +52,26 @@
53 52
 				<div class="commit-form">
54 53
 					<h3>{{.i18n.Tr "repo.commit_changes"}}</h3>
55 54
 					<div class="field">
56
-						<input name="commit_summary" placeholder="{{if .IsNewFile}}{{.i18n.Tr "repo.add"}} '{{.TreeName}}/<filename>'{{else}}{{.i18n.Tr "repo.update"}} '{{.TreeName}}'{{end}}" value="{{.CommitSummary}}">
55
+						<input name="commit_summary" placeholder="{{if .IsNewFile}}{{.i18n.Tr "repo.add"}} '{{.TreeName}}/<filename>'{{else}}{{.i18n.Tr "repo.update"}} '{{.TreeName}}'{{end}}" value="{{.commit_summary}}">
57 56
 					</div>
58 57
 					<div class="field">
59
-						<textarea name="commit_message" placeholder="{{.i18n.Tr "repo.default_commit_message"}}">{{.CommitMessage}}</textarea>
58
+						<textarea name="commit_message" placeholder="{{.i18n.Tr "repo.default_commit_message"}}">{{.commit_message}}</textarea>
60 59
 					</div>
61
-					<div class="quick-pull-choice js-quick-pull-choice ">
60
+					<div class="quick-pull-choice js-quick-pull-choice">
62 61
 						<dl class="form-group">
63 62
 							<dd>
64 63
 						 		<div class="form-checkbox">
65 64
 									<label>
66
-										<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="direct"{{if eq .CommitChoice "direct"}} checked="checked"{{end}}>
65
+										<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="direct"{{if eq .commit_choice "direct"}} checked="checked"{{end}}>
67 66
 										<i class="octicon octicon-git-commit" height="16" width="14"></i>
68
-										{{.CommitDirectlyToThisBranch | Safe}}
67
+										{{.i18n.Tr "repo.editor.commit_directly_to_this_branch" .BranchName | Safe}}
69 68
 									</label>
70 69
 								</div>
71 70
 								<div class="form-checkbox">
72 71
 									<label>
73
-										<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}}>
72
+										<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="commit-to-new-branch"{{if eq .commit_choice "commit-to-new-branch"}} checked="checked"{{end}}>
74 73
 										<i class="octicon octicon-git-pull-request" height="16" width="12"></i>
75
-										{{.CreateNewBranch | Safe}}
74
+										{{.i18n.Tr "repo.editor.create_new_branch" | Safe}}
76 75
 									</label>
77 76
 								</div>
78 77
 							</dd>
@@ -80,7 +79,7 @@
80 79
 						<div class="quick-pull-branch-name">
81 80
 							<div class="new-branch-name-input{{if .Err_Branchname}} error{{end}}">
82 81
 								<i class="octicon octicon-git-branch quick-pull-new-branch-icon" height="16" width="10"></i>
83
-								<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…">
82
+								<input type="text" name="new_branch_name" value="{{.new_branch_name}}" class="form-control input-contrast mr-2 js-quick-pull-new-branch-name" placeholder="New branch name…">
84 83
 								<span class="text-muted js-quick-pull-normalization-info"></span>
85 84
 							</div>
86 85
 						</div>