Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create new branch from branch selection dropdown #2130

Merged
merged 4 commits into from
Oct 15, 2017

Conversation

lafriks
Copy link
Member

@lafriks lafriks commented Jul 9, 2017

Also fix Branches and Tags tab alignment in branch selection select box

Screenshot:
attels

@lunny lunny added the type/feature Completely new functionality. Can only be merged if feature freeze is not active. label Jul 9, 2017
@lunny lunny added this to the 1.3.0 milestone Jul 9, 2017
@lafriks lafriks force-pushed the feature/create_new_branch branch from 12ac6e2 to 25d4619 Compare July 9, 2017 11:01
@lafriks lafriks changed the title Create new branch from branch choose select Create new branch from branch selection dropdown Jul 9, 2017
@lafriks lafriks force-pushed the feature/create_new_branch branch 2 times, most recently from 486a881 to 8646ee5 Compare July 9, 2017 12:15
Copy link
Member

@bkcsoft bkcsoft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and a question

models/repo.go Outdated
return fmt.Errorf("UpdateLocalCopyBranch: %v", err)
}

if err = repo.CheckoutNewBranch(commit, branchName); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure that we need a clone to do this? Since one can create new branches in a bare repo...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is for creating new branch based on existing branch/tag/commit, so no bare repositories. I was basing it exactly on your pointed out code. Branch can be created directly in real repository without cloning but I just thought that there are reasons why existing branch creation from branch was made this way

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I noticed that after I commented on it. I wonder why it does that 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is very good question that I would really be interested to get answer, it could be just for that it is also used by file editor but could be also other reasons, hard to tell

@@ -523,6 +523,10 @@ func RegisterRoutes(m *macaron.Macaron) {
return
}
})

m.Group("/branches", func() {
m.Get("/_new/*", context.RepoRef(), repo.CreateBranch)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why _new instead of new ? (Except that we'd need to add another reserved name)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to clarify, I'm fairly certain that no one would create a branch called "new" anyhow 😆

Copy link
Member Author

@lafriks lafriks Jul 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was following same naming rules that are for editing files and I don't think we need to add new reserved name, it is completely new group under repo

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be POST? GET requests shouldn't update state.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ethantkoenig it would be right way but semantic-ui dropdown does not have enough events exposed to do that :(

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lafriks Can't we just add some Javascript/JQuery to make a POST request?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ethantkoenig not with jquery if only doing with some js timeouts to check if semantic ui dropdown has rendered that link and than binding on click but that is quite dirty that I would want to avoid. Also it could be done using <a onclick with bunch of javascript but that code also seems more like hack than good solution

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lafriks If we use GET, then there will no be CSRF check

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

models/repo.go Outdated
@@ -2363,3 +2401,28 @@ func (repo *Repository) CreateNewBranch(doer *User, oldBranchName, branchName st

return nil
}

// CreateNewBranchFromCommit creates a new repository branch
func (repo *Repository) CreateNewBranchFromCommit(doer *User, commit, branchName string) (err error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put this function in models/repo_branch.go instead. Let's not add more to the God File unless we have to 😄

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should I also move CreateNewBranch function that was already there to repo_branch.go? As these functions are doing very similar things I just did not want them to be in different files

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lafriks Yes please 🙂

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe if possible make it the same function (renaming oldBranch to baseRef or similar)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They have different functionality a bit and different checks and some code is called in different order, so making all one function would overcomplicate it

func testCreateBranch(t *testing.T, session *TestSession, user, repo, oldRefName, newBranchName string, expectedStatus int) string {
req := NewRequest(t, "GET", path.Join(user, repo, "branches/_new", oldRefName)+"?name="+url.QueryEscape(newBranchName))
resp := session.MakeRequest(t, req, expectedStatus)
assert.EqualValues(t, expectedStatus, resp.HeaderCode)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line isn't necessary, session.MakeRequest(..) already checks

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix, I did write this code before MakeRequest was changed and forgot to remove that line

@@ -523,6 +523,10 @@ func RegisterRoutes(m *macaron.Macaron) {
return
}
})

m.Group("/branches", func() {
m.Get("/_new/*", context.RepoRef(), repo.CreateBranch)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be POST? GET requests shouldn't update state.

@@ -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 class="ui floating filter dropdown" data-can-create-branch="{{if .Repository.CanCreateBranch}}true{{else}}false{{end}}" data-no-results="{{.i18n.Tr "repo.pulls.no_results"}}">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can just do data-can-create-branch="{{.Repository.CanCreateBranch}}"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did not work for me...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@lafriks lafriks force-pushed the feature/create_new_branch branch 5 times, most recently from f29ceae to 29997f0 Compare July 12, 2017 21:28
@lafriks
Copy link
Member Author

lafriks commented Jul 12, 2017

@bkcsoft, @ethantkoenig fixed with all your suggestions, please review

@tboerger tboerger added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Jul 12, 2017
@lafriks lafriks force-pushed the feature/create_new_branch branch 2 times, most recently from a8d9b11 to 835cc95 Compare July 12, 2017 21:47
Copy link
Member

@bkcsoft bkcsoft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 question, 1 suggestion. Otherwise LGTM

return
}

if len(form.NewBranchName) > 100 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this limit taken from? Why is it not a constant? (in go-gitea/git) :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bkcsoft it is limit used also in other places in gitea code where branch name can be entered (editor for example)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No clue 😆 Hence why I'm asking 😉

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bkcsoft @ethantkoenig suggested that limit and later I found it also in other places in code, so that's why it is so :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggested it because I found it in other places 😆

Copy link
Member

@bkcsoft bkcsoft Aug 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I'm suggesting making that a global constant variable in code.gitea.io/git :trollface:

}

if _, err := ctx.Repo.GitRepo.GetTag(form.NewBranchName); err == nil {
ctx.Flash.Error(ctx.Tr("repo.branch.tag_already_exists", form.NewBranchName))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be repo.branch.tag_collision

@ethantkoenig
Copy link
Member

As things currently are, I can't create a branch called "mast", since searing for "mast" will match the master branch (so the "Create new branch" button won't show). Maybe the button should always show, but be disabled for exact matches?

@lafriks
Copy link
Member Author

lafriks commented Jul 13, 2017

You are right but with this dropdown I don't know if it is possible. I will check if I can work around somehow

@lafriks
Copy link
Member Author

lafriks commented Jul 14, 2017

@ethantkoenig @bkcsoft I rewrote javascript side to allow creating branches also with names that partially match existing branches as suggested, please review

@lafriks lafriks force-pushed the feature/create_new_branch branch 3 times, most recently from 1770bae to c21cf76 Compare July 16, 2017 00:22
@lafriks
Copy link
Member Author

lafriks commented Jul 16, 2017

As I could not solve small remaining issue that no data found would still show up sometimes together with create new branch item, I did complete JavaScript branch/tag dropdown rewrite to not use semantic ui js but VueJS. As a plus works a lot faster and in future more extendable.

@lafriks lafriks force-pushed the feature/create_new_branch branch 3 times, most recently from 650e35b to fd7e742 Compare July 18, 2017 10:02
@codecov-io
Copy link

codecov-io commented Sep 23, 2017

Codecov Report

Merging #2130 into master will decrease coverage by 0.11%.
The diff coverage is 6.89%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2130      +/-   ##
==========================================
- Coverage    27.1%   26.98%   -0.12%     
==========================================
  Files          87       87              
  Lines       17191    17283      +92     
==========================================
+ Hits         4659     4664       +5     
- Misses      11852    11939      +87     
  Partials      680      680
Impacted Files Coverage Δ
models/repo.go 13.12% <ø> (+0.16%) ⬆️
models/repo_branch.go 8.73% <0%> (-24.61%) ⬇️
models/error.go 18.93% <0%> (-1%) ⬇️
modules/validation/binding.go 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c25303b...3d0a597. Read the comment docs.

@lafriks lafriks added pr/wip This PR is not ready for review and removed pr/wip This PR is not ready for review labels Sep 23, 2017
@lafriks
Copy link
Member Author

lafriks commented Sep 25, 2017

@ethantkoenig need your approval

Copy link
Member

@ethantkoenig ethantkoenig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not working when I try it locally (eae7ad5); the link to create a new branch never appears. Never mind
image

// This function checks out target commit by default, it is safe to assume subsequent
// operations are operating against target commit when caller has confidence for no race condition.
func UpdateLocalCopyToCommit(repoPath, localPath, commit string) error {
if !com.IsExist(localPath) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is duplicated code; this if/else can be replaced by

UpdateLocalCopyBranch(repoPath, localPath, repo.DefaultBranch)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ethantkoenig no it can not as they are different and calls methods in different order. Code from UpdateLocalCopyBranch will fail in some cases if not updated in correct order (at least for creating new branch from commit/tag)

// It creates a new clone if local copy does not exist.
// This function checks out target commit by default, it is safe to assume subsequent
// operations are operating against target commit when caller has confidence for no race condition.
func UpdateLocalCopyToCommit(repoPath, localPath, commit string) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the function should only be called when the repo's "mutex" has been acquired, should we make it private? Similarly, for repo.UpdateLocalCopyToCommit?

ctx.Flash.Error(ctx.Tr("repo.branch.branch_already_exists", branch.Name))
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchName)
return
} else if (len(branch.Name) < len(form.NewBranchName) && branch.Name+"/" == form.NewBranchName[0:len(branch.Name)+1]) ||
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we move this condition to a helper function, something like BranchNamesConflict(name1, name2)? It could be useful in other places, and would make the code more readable IMO.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ethantkoenig I have no idea to where to move this functions

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

models.(*Repository).BranchNameConflict(form.NewBranchName) perhaps?

@lafriks
Copy link
Member Author

lafriks commented Sep 25, 2017

@ethantkoenig from what it looks like from screenshot you are not logged in. For branch creation to show up you must be logged in and have write access to that repository

@ethantkoenig
Copy link
Member

@lafriks Wow, not sure how I missed that 🤦‍♂️. Links appearing as they should.

@webjoel
Copy link
Contributor

webjoel commented Oct 11, 2017

index.css gets created by make stylesheets from less file. So shouldn't matter.
you have to call that for yourself.

can someone finish the job, I'm waiting for this feature :)

@lafriks lafriks force-pushed the feature/create_new_branch branch 2 times, most recently from dbb75f0 to f7ebb60 Compare October 15, 2017 02:26
@lunny
Copy link
Member

lunny commented Oct 15, 2017

LGTM

@tboerger tboerger added lgtm/done This PR has enough approvals to get merged. There are no important open reservations anymore. and removed lgtm/need 1 This PR needs approval from one additional maintainer to be merged. labels Oct 15, 2017
errs.Add([]string{name}, ErrGitRefName, "GitRefName")
return false, errs
}
parts := strings.Split(str, "/")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about using a regex instead of doing similar checks twice? https://stackoverflow.com/a/12093994

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That won't work in golang as its regex does not support all required features. I tried that exact stackoverflow topic regex first when implementing this

ctx.Flash.Error(ctx.Tr("repo.branch.branch_already_exists", branch.Name))
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchName)
return
} else if (len(branch.Name) < len(form.NewBranchName) && branch.Name+"/" == form.NewBranchName[0:len(branch.Name)+1]) ||
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

models.(*Repository).BranchNameConflict(form.NewBranchName) perhaps?

@lafriks
Copy link
Member Author

lafriks commented Oct 15, 2017

@ethantkoenig @bkcsoft moved branch name validation to model

if err := repo.CheckBranchName(branchName); err != nil {
return err
}

repoWorkingPool.CheckIn(com.ToStr(repo.ID))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do this before checking the branch-name, otherwise you'll end up with race conditions

if err := repo.CheckBranchName(branchName); err != nil {
return err
}

repoWorkingPool.CheckIn(com.ToStr(repo.ID))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bkcsoft fixed both

} else {
err = ctx.Repo.Repository.CreateNewBranchFromCommit(ctx.User, ctx.Repo.BranchName, form.NewBranchName)
}
if err != nil {
ctx.Handle(500, "CreateNewBranch", err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so 500 error if the name is invalid?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No there is L56-L73 special error type checks before this - this one is for unexpected errors

return err
}

for _, branch := range branches {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of doing this, how about something like this that scales to thousands of branches?

if _, err := gitRepo.GetBranch(name); err != nil {
  return ErrConflict(name)
}
if strings.Contains(name, "/") {
  for index := strings.LastIndex(name, "/"); index > 0; index := strings.LastIndex(name, "/") {
    if conflict, err := gitRepo.GetBranch(name[:index]); err != nil {
      return ErrConflict(name[:index])
    }
  }
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not the same (if name is feat and there already exists branch feat/test) this code won't return error

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One option is to just try the git branch ... command, and see if it succeeds or not. I assume that internally git has an efficient way to check for naming conflicts.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that gitRepo.CreateBranch will throw a collision error no?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But then CheckBranchName will only provide part of validation (as I understand that that was an initial request to create it at first place to reuse it in other places later). Also currently GetBranches is called on every repo page load (in ctx RepoAssignment) so it's usage here anyway won't be that big deal

@lafriks lafriks merged commit f3833b7 into go-gitea:master Oct 15, 2017
@lafriks lafriks deleted the feature/create_new_branch branch October 15, 2017 19:59
@go-gitea go-gitea locked and limited conversation to collaborators Nov 23, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
lgtm/done This PR has enough approvals to get merged. There are no important open reservations anymore. type/feature Completely new functionality. Can only be merged if feature freeze is not active.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants