forked from gitea/gitea
		
	Almost done diff page
This commit is contained in:
		
							parent
							
								
									4b9eef50c9
								
							
						
					
					
						commit
						dd6246877d
					
				
							
								
								
									
										137
									
								
								diff.txt
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								diff.txt
									
									
									
									
									
								
							| @ -1,137 +0,0 @@ | ||||
| commit c1a3d4fefbbbf332cd1cedda66e93bf40cc9713d | ||||
| Author: Unknown <joe2010xtmf@163.com> | ||||
| Date:   Tue Mar 25 21:37:18 2014 -0400 | ||||
| 
 | ||||
|     Add mail notify for creating issue | ||||
| 
 | ||||
| diff --git a/gogs.go b/gogs.go | ||||
| index b62580f..f5a328a 100644 | ||||
| --- a/gogs.go | ||||
| +++ b/gogs.go | ||||
| @@ -19,7 +19,7 @@ import ( | ||||
|  // Test that go1.2 tag above is included in builds. main.go refers to this definition. | ||||
|  const go12tag = true | ||||
|   | ||||
| -const APP_VER = "0.1.7.0325" | ||||
| +const APP_VER = "0.1.8.0325" | ||||
|   | ||||
|  func init() { | ||||
|  	base.AppVer = APP_VER | ||||
| diff --git a/models/issue.go b/models/issue.go | ||||
| index 2bdd083..2de6568 100644 | ||||
| --- a/models/issue.go | ||||
| +++ b/models/issue.go | ||||
| @@ -59,7 +59,6 @@ func CreateIssue(userId, repoId, milestoneId, assigneeId int64, name, labels, co | ||||
|  		Content:     content, | ||||
|  	} | ||||
|  	_, err = orm.Insert(issue) | ||||
| -	// TODO: newIssueAction | ||||
|  	return issue, err | ||||
|  } | ||||
|   | ||||
| diff --git a/modules/mailer/mail.go b/modules/mailer/mail.go | ||||
| index 92acd20..d0decbe 100644 | ||||
| --- a/modules/mailer/mail.go | ||||
| +++ b/modules/mailer/mail.go | ||||
| @@ -6,6 +6,7 @@ package mailer | ||||
|   | ||||
|  import ( | ||||
|  	"encoding/hex" | ||||
| +	"errors" | ||||
|  	"fmt" | ||||
|   | ||||
|  	"github.com/gogits/gogs/models" | ||||
| @@ -15,12 +16,17 @@ import ( | ||||
|  ) | ||||
|   | ||||
|  // Create New mail message use MailFrom and MailUser | ||||
| -func NewMailMessage(To []string, subject, body string) Message { | ||||
| -	msg := NewHtmlMessage(To, base.MailService.User, subject, body) | ||||
| +func NewMailMessageFrom(To []string, from, subject, body string) Message { | ||||
| +	msg := NewHtmlMessage(To, from, subject, body) | ||||
|  	msg.User = base.MailService.User | ||||
|  	return msg | ||||
|  } | ||||
|   | ||||
| +// Create New mail message use MailFrom and MailUser | ||||
| +func NewMailMessage(To []string, subject, body string) Message { | ||||
| +	return NewMailMessageFrom(To, base.MailService.User, subject, body) | ||||
| +} | ||||
| + | ||||
|  func GetMailTmplData(user *models.User) map[interface{}]interface{} { | ||||
|  	data := make(map[interface{}]interface{}, 10) | ||||
|  	data["AppName"] = base.AppName | ||||
| @@ -84,3 +90,33 @@ func SendActiveMail(r *middleware.Render, user *models.User) { | ||||
|   | ||||
|  	SendAsync(&msg) | ||||
|  } | ||||
| + | ||||
| +// SendNotifyMail sends mail notification of all watchers. | ||||
| +func SendNotifyMail(userId, repoId int64, userName, repoName, subject, content string) error { | ||||
| +	watches, err := models.GetWatches(repoId) | ||||
| +	if err != nil { | ||||
| +		return errors.New("mail.NotifyWatchers(get watches): " + err.Error()) | ||||
| +	} | ||||
| + | ||||
| +	tos := make([]string, 0, len(watches)) | ||||
| +	for i := range watches { | ||||
| +		uid := watches[i].UserId | ||||
| +		if userId == uid { | ||||
| +			continue | ||||
| +		} | ||||
| +		u, err := models.GetUserById(uid) | ||||
| +		if err != nil { | ||||
| +			return errors.New("mail.NotifyWatchers(get user): " + err.Error()) | ||||
| +		} | ||||
| +		tos = append(tos, u.Email) | ||||
| +	} | ||||
| + | ||||
| +	if len(tos) == 0 { | ||||
| +		return nil | ||||
| +	} | ||||
| + | ||||
| +	msg := NewMailMessageFrom(tos, userName, subject, content) | ||||
| +	msg.Info = fmt.Sprintf("Subject: %s, send notify emails", subject) | ||||
| +	SendAsync(&msg) | ||||
| +	return nil | ||||
| +} | ||||
| diff --git a/modules/mailer/mailer.go b/modules/mailer/mailer.go | ||||
| index da63e01..63861d8 100644 | ||||
| --- a/modules/mailer/mailer.go | ||||
| +++ b/modules/mailer/mailer.go | ||||
| @@ -33,7 +33,7 @@ func (m Message) Content() string { | ||||
|  	} | ||||
|   | ||||
|  	// create mail content | ||||
| -	content := "From: " + m.User + "<" + m.From + | ||||
| +	content := "From: " + m.From + "<" + m.User + | ||||
|  		">\r\nSubject: " + m.Subject + "\r\nContent-Type: " + contentType + "\r\n\r\n" + m.Body | ||||
|  	return content | ||||
|  } | ||||
| diff --git a/routers/repo/issue.go b/routers/repo/issue.go | ||||
| index fc5bb98..242593f 100644 | ||||
| --- a/routers/repo/issue.go | ||||
| +++ b/routers/repo/issue.go | ||||
| @@ -13,6 +13,7 @@ import ( | ||||
|  	"github.com/gogits/gogs/modules/auth" | ||||
|  	"github.com/gogits/gogs/modules/base" | ||||
|  	"github.com/gogits/gogs/modules/log" | ||||
| +	"github.com/gogits/gogs/modules/mailer" | ||||
|  	"github.com/gogits/gogs/modules/middleware" | ||||
|  ) | ||||
|   | ||||
| @@ -86,6 +87,14 @@ func CreateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat | ||||
|  		return | ||||
|  	} | ||||
|   | ||||
| +	// Mail watchers. | ||||
| +	if base.Service.NotifyMail { | ||||
| +		if err = mailer.SendNotifyMail(ctx.User.Id, ctx.Repo.Repository.Id, ctx.User.Name, ctx.Repo.Repository.Name, issue.Name, issue.Content); err != nil { | ||||
| +			ctx.Handle(200, "issue.CreateIssue", err) | ||||
| +			return | ||||
| +		} | ||||
| +	} | ||||
| + | ||||
|  	log.Trace("%d Issue created: %d", ctx.Repo.Repository.Id, issue.Id) | ||||
|  	ctx.Redirect(fmt.Sprintf("/%s/%s/issues/%d", params["username"], params["reponame"], issue.Index)) | ||||
|  } | ||||
| @ -15,6 +15,8 @@ import ( | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/gogits/git" | ||||
| 
 | ||||
| 	"github.com/gogits/gogs/modules/base" | ||||
| ) | ||||
| 
 | ||||
| // RepoFile represents a file object in git repository. | ||||
| @ -249,6 +251,10 @@ type DiffLine struct { | ||||
| 	Content  string | ||||
| } | ||||
| 
 | ||||
| func (d DiffLine) GetType() int { | ||||
| 	return d.Type | ||||
| } | ||||
| 
 | ||||
| type DiffSection struct { | ||||
| 	Name  string | ||||
| 	Lines []*DiffLine | ||||
| @ -274,16 +280,20 @@ const DIFF_HEAD = "diff --git " | ||||
| 
 | ||||
| func ParsePatch(reader io.Reader) (*Diff, error) { | ||||
| 	scanner := bufio.NewScanner(reader) | ||||
| 	var curFile *DiffFile | ||||
| 	curSection := &DiffSection{ | ||||
| 		Lines: make([]*DiffLine, 0, 10), | ||||
| 	} | ||||
| 	//var leftLine, rightLine int | ||||
| 	var ( | ||||
| 		curFile    *DiffFile | ||||
| 		curSection = &DiffSection{ | ||||
| 			Lines: make([]*DiffLine, 0, 10), | ||||
| 		} | ||||
| 
 | ||||
| 		leftLine, rightLine int | ||||
| 	) | ||||
| 
 | ||||
| 	diff := &Diff{Files: make([]*DiffFile, 0)} | ||||
| 	var i int | ||||
| 	for scanner.Scan() { | ||||
| 		line := scanner.Text() | ||||
| 		fmt.Println(i, line) | ||||
| 		// fmt.Println(i, line) | ||||
| 		if strings.HasPrefix(line, "+++ ") || strings.HasPrefix(line, "--- ") { | ||||
| 			continue | ||||
| 		} | ||||
| @ -293,31 +303,37 @@ func ParsePatch(reader io.Reader) (*Diff, error) { | ||||
| 			continue | ||||
| 		} | ||||
| 		if line[0] == ' ' { | ||||
| 			diffLine := &DiffLine{Type: DIFF_LINE_PLAIN, Content: line} | ||||
| 			diffLine := &DiffLine{Type: DIFF_LINE_PLAIN, Content: line, LeftIdx: leftLine, RightIdx: rightLine} | ||||
| 			leftLine++ | ||||
| 			rightLine++ | ||||
| 			curSection.Lines = append(curSection.Lines, diffLine) | ||||
| 			continue | ||||
| 		} else if line[0] == '@' { | ||||
| 			curSection = &DiffSection{} | ||||
| 			curFile.Sections = append(curFile.Sections, curSection) | ||||
| 			ss := strings.Split(line, "@@") | ||||
| 			diffLine := &DiffLine{Type: DIFF_LINE_SECTION, Content: "@@" + ss[len(ss)-2] + "@@"} | ||||
| 			diffLine := &DiffLine{Type: DIFF_LINE_SECTION, Content: line} | ||||
| 			curSection.Lines = append(curSection.Lines, diffLine) | ||||
| 
 | ||||
| 			if len(ss[len(ss)-1]) > 0 { | ||||
| 				diffLine = &DiffLine{Type: DIFF_LINE_PLAIN, Content: ss[len(ss)-1]} | ||||
| 				curSection.Lines = append(curSection.Lines, diffLine) | ||||
| 			} | ||||
| 			// Parse line number. | ||||
| 			ranges := strings.Split(ss[len(ss)-2][1:], " ") | ||||
| 			leftLine, _ = base.StrTo(strings.Split(ranges[0], ",")[0][1:]).Int() | ||||
| 			rightLine, _ = base.StrTo(strings.Split(ranges[1], ",")[0]).Int() | ||||
| 			continue | ||||
| 		} else if line[0] == '+' { | ||||
| 			curFile.Addition++ | ||||
| 			diff.TotalAddition++ | ||||
| 			diffLine := &DiffLine{Type: DIFF_LINE_ADD, Content: line} | ||||
| 			diffLine := &DiffLine{Type: DIFF_LINE_ADD, Content: line, RightIdx: rightLine} | ||||
| 			rightLine++ | ||||
| 			curSection.Lines = append(curSection.Lines, diffLine) | ||||
| 			continue | ||||
| 		} else if line[0] == '-' { | ||||
| 			curFile.Deletion++ | ||||
| 			diff.TotalDeletion++ | ||||
| 			diffLine := &DiffLine{Type: DIFF_LINE_DEL, Content: line} | ||||
| 			diffLine := &DiffLine{Type: DIFF_LINE_DEL, Content: line, LeftIdx: leftLine} | ||||
| 			if leftLine > 0 { | ||||
| 				leftLine++ | ||||
| 			} | ||||
| 			curSection.Lines = append(curSection.Lines, diffLine) | ||||
| 			continue | ||||
| 		} | ||||
| @ -365,8 +381,20 @@ func GetDiff(repoPath, commitid string) (*Diff, error) { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// First commit of repository. | ||||
| 	if commit.ParentCount() == 0 { | ||||
| 		return &Diff{}, err | ||||
| 		rd, wr := io.Pipe() | ||||
| 		go func() { | ||||
| 			cmd := exec.Command("git", "show", commitid) | ||||
| 			cmd.Dir = repoPath | ||||
| 			cmd.Stdout = wr | ||||
| 			cmd.Stdin = os.Stdin | ||||
| 			cmd.Stderr = os.Stderr | ||||
| 			cmd.Run() | ||||
| 			wr.Close() | ||||
| 		}() | ||||
| 		defer rd.Close() | ||||
| 		return ParsePatch(rd) | ||||
| 	} | ||||
| 
 | ||||
| 	rd, wr := io.Pipe() | ||||
| @ -377,47 +405,8 @@ func GetDiff(repoPath, commitid string) (*Diff, error) { | ||||
| 		cmd.Stdin = os.Stdin | ||||
| 		cmd.Stderr = os.Stderr | ||||
| 		cmd.Run() | ||||
| 		//if err != nil { | ||||
| 		//	return nil, err | ||||
| 		//} | ||||
| 		wr.Close() | ||||
| 	}() | ||||
| 
 | ||||
| 	defer rd.Close() | ||||
| 
 | ||||
| 	return ParsePatch(rd) | ||||
| } | ||||
| 
 | ||||
| /*func GetDiff(repoPath, commitid string) (*Diff, error) { | ||||
| 	stdout, _, err := com.ExecCmdDir(repoPath, "git", "show", commitid) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Sperate parts by file. | ||||
| 	startIndex := strings.Index(stdout, "diff --git ") + 12 | ||||
| 
 | ||||
| 	// First part is commit information. | ||||
| 	// Check if it's a merge. | ||||
| 	mergeIndex := strings.Index(stdout[:startIndex], "merge") | ||||
| 	if mergeIndex > -1 { | ||||
| 		mergeCommit := strings.SplitN(strings.Split(stdout[:startIndex], "\n")[1], "", 3)[2] | ||||
| 		return GetDiff(repoPath, mergeCommit) | ||||
| 	} | ||||
| 
 | ||||
| 	parts := strings.Split(stdout[startIndex:], "diff --git ") | ||||
| 	diff := &Diff{NumFiles: len(parts)} | ||||
| 	diff.Files = make([]*DiffFile, 0, diff.NumFiles) | ||||
| 	for _, part := range parts { | ||||
| 		infos := strings.SplitN(part, "\n", 6) | ||||
| 		maxIndex := len(infos) - 1 | ||||
| 		infos[maxIndex] = strings.TrimSuffix(strings.TrimSuffix(infos[maxIndex], "\n"), "\n\\ No newline at end of file") | ||||
| 
 | ||||
| 		file := &DiffFile{ | ||||
| 			Name:    strings.TrimPrefix(strings.Split(infos[0], " ")[0], "a/"), | ||||
| 			Content: strings.Split(infos[maxIndex], "\n"), | ||||
| 		} | ||||
| 		diff.Files = append(diff.Files, file) | ||||
| 	} | ||||
| 	return diff, nil | ||||
| }*/ | ||||
|  | ||||
| @ -173,14 +173,23 @@ type Comment struct { | ||||
| 
 | ||||
| // CreateComment creates comment of issue or commit. | ||||
| func CreateComment(userId, issueId, commitId, line int64, content string) error { | ||||
| 	_, err := orm.Insert(&Comment{ | ||||
| 		PosterId: userId, | ||||
| 		IssueId:  issueId, | ||||
| 		CommitId: commitId, | ||||
| 		Line:     line, | ||||
| 		Content:  content, | ||||
| 	}) | ||||
| 	return err | ||||
| 	sess := orm.NewSession() | ||||
| 	defer sess.Close() | ||||
| 	sess.Begin() | ||||
| 
 | ||||
| 	if _, err := orm.Insert(&Comment{PosterId: userId, IssueId: issueId, | ||||
| 		CommitId: commitId, Line: line, Content: content, | ||||
| 	}); err != nil { | ||||
| 		sess.Rollback() | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	rawSql := "UPDATE `issue` SET num_comments = num_comments + 1 WHERE id = ?" | ||||
| 	if _, err := sess.Exec(rawSql, issueId); err != nil { | ||||
| 		sess.Rollback() | ||||
| 		return err | ||||
| 	} | ||||
| 	return sess.Commit() | ||||
| } | ||||
| 
 | ||||
| // GetIssueComments returns list of comment by given issue id. | ||||
|  | ||||
| @ -70,5 +70,6 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{ | ||||
| 	"SubStr": func(str string, start, length int) string { | ||||
| 		return str[start : start+length] | ||||
| 	}, | ||||
| 	"DiffTypeToStr": DiffTypeToStr, | ||||
| 	"DiffTypeToStr":     DiffTypeToStr, | ||||
| 	"DiffLineTypeToStr": DiffLineTypeToStr, | ||||
| } | ||||
|  | ||||
| @ -552,3 +552,15 @@ func DiffTypeToStr(diffType int) string { | ||||
| 		return "unknown" | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func DiffLineTypeToStr(diffType int) string { | ||||
| 	switch diffType { | ||||
| 	case 2: | ||||
| 		return "add" | ||||
| 	case 3: | ||||
| 		return "del" | ||||
| 	case 4: | ||||
| 		return "tag" | ||||
| 	} | ||||
| 	return "same" | ||||
| } | ||||
|  | ||||
| @ -980,6 +980,11 @@ html, body { | ||||
|     padding: 20px; | ||||
| } | ||||
| 
 | ||||
| .diff-file-box .code-diff tbody tr.tag-code td, .diff-file-box .code-diff tbody tr.tag-code pre { | ||||
|     background-color: #E0E0E0 !important; | ||||
|     border-color: #ADADAD !important; | ||||
| } | ||||
| 
 | ||||
| .diff-file-box .code-diff tbody tr.add-code td, .diff-file-box .code-diff tbody tr.add-code pre { | ||||
|     background-color: #d1ffd6 !important; | ||||
|     border-color: #b4e2b4 !important; | ||||
|  | ||||
| @ -71,7 +71,6 @@ func Single(ctx *middleware.Context, params martini.Params) { | ||||
| 	// Branches. | ||||
| 	brs, err := models.GetBranches(params["username"], params["reponame"]) | ||||
| 	if err != nil { | ||||
| 		//log.Error("repo.Single(GetBranches): %v", err) | ||||
| 		ctx.Handle(404, "repo.Single(GetBranches)", err) | ||||
| 		return | ||||
| 	} else if ctx.Repo.Repository.IsBare { | ||||
| @ -79,14 +78,11 @@ func Single(ctx *middleware.Context, params martini.Params) { | ||||
| 		ctx.HTML(200, "repo/single") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.Data["Branches"] = brs | ||||
| 
 | ||||
| 	repoFile, err := models.GetTargetFile(params["username"], params["reponame"], | ||||
| 		params["branchname"], params["commitid"], treename) | ||||
| 
 | ||||
| 	if err != nil && err != models.ErrRepoFileNotExist { | ||||
| 		//log.Error("repo.Single(GetTargetFile): %v", err) | ||||
| 		ctx.Handle(404, "repo.Single(GetTargetFile)", err) | ||||
| 		return | ||||
| 	} | ||||
| @ -133,7 +129,6 @@ func Single(ctx *middleware.Context, params martini.Params) { | ||||
| 		files, err := models.GetReposFiles(params["username"], params["reponame"], | ||||
| 			params["branchname"], params["commitid"], treename) | ||||
| 		if err != nil { | ||||
| 			//log.Error("repo.Single(GetReposFiles): %v", err) | ||||
| 			ctx.Handle(404, "repo.Single(GetReposFiles)", err) | ||||
| 			return | ||||
| 		} | ||||
| @ -189,7 +184,7 @@ func Single(ctx *middleware.Context, params martini.Params) { | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Get latest commit according username and repo name | ||||
| 	// Get latest commit according username and repo name. | ||||
| 	commit, err := models.GetCommit(params["username"], params["reponame"], | ||||
| 		params["branchname"], params["commitid"]) | ||||
| 	if err != nil { | ||||
|  | ||||
| @ -65,12 +65,12 @@ | ||||
|                     <tbody> | ||||
|                         {{range .Sections}} | ||||
|                         {{range .Lines}} | ||||
|                         <tr class="same-code nl-1 ol-1"> | ||||
|                         <tr class="{{DiffLineTypeToStr .Type}}-code nl-1 ol-1"> | ||||
|                             <td class="lines-num lines-num-old"> | ||||
|                                 <span rel="L1"></span> | ||||
|                                 <span rel="L1">{{if .LeftIdx}}{{.LeftIdx}}{{end}}</span> | ||||
|                             </td> | ||||
|                             <td class="lines-num lines-num-new"> | ||||
|                                 <span rel="L1"></span> | ||||
|                                 <span rel="L1">{{if .RightIdx}}{{.RightIdx}}{{end}}</span> | ||||
|                             </td> | ||||
|                             <td class="lines-code"> | ||||
|                                 <pre>{{.Content}}</pre> | ||||
|  | ||||
							
								
								
									
										1
									
								
								web.go
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								web.go
									
									
									
									
									
								
							| @ -159,7 +159,6 @@ func runWeb(*cli.Context) { | ||||
| 		r.Get("/commits/:branchname", repo.Commits) | ||||
| 	}, ignSignIn, middleware.RepoAssignment(true)) | ||||
| 
 | ||||
| 	// TODO: implement single commit page | ||||
| 	m.Get("/:username/:reponame/commit/:commitid/**", ignSignIn, middleware.RepoAssignment(true), repo.Diff) | ||||
| 	m.Get("/:username/:reponame/commit/:commitid", ignSignIn, middleware.RepoAssignment(true), repo.Diff) | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Unknown
						Unknown