Skip to content

Commit 335cb15

Browse files
committed
Add new rewrite command
1 parent 8607aec commit 335cb15

File tree

5 files changed

+162
-25
lines changed

5 files changed

+162
-25
lines changed

command/rewrite.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package command
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"github.com/DEVELOPEST/gtm-core/project"
7+
"github.com/DEVELOPEST/gtm-core/scm"
8+
"io"
9+
"log"
10+
"os"
11+
"strings"
12+
13+
"github.com/mitchellh/cli"
14+
)
15+
16+
// CommitCmd struct contain methods for commit command
17+
type RewriteCmd struct {
18+
UI cli.Ui
19+
}
20+
21+
// NewCommit returns new CommitCmd struct
22+
func NewRewrite() (cli.Command, error) {
23+
return RewriteCmd{}, nil
24+
}
25+
26+
// Help returns help for commit command
27+
func (c RewriteCmd) Help() string {
28+
helpText := `
29+
Usage: gtm rewrite [options]
30+
31+
Automatically called on git history rewrite. Do not use manually!.
32+
`
33+
return strings.TrimSpace(helpText)
34+
}
35+
36+
// Run executes commit commands with args
37+
func (c RewriteCmd) Run(args []string) int {
38+
39+
reader := bufio.NewReader(os.Stdin)
40+
for {
41+
input, err := reader.ReadString('\n')
42+
if err != nil {
43+
if err != io.EOF {
44+
log.Fatal(err)
45+
}
46+
break
47+
}
48+
input = strings.TrimSpace(input)
49+
hashes := strings.Split(input, " ")
50+
fmt.Println(hashes[0])
51+
fmt.Println(hashes[1])
52+
err = scm.RewriteNote(hashes[0], hashes[1], project.NoteNameSpace)
53+
54+
if err != nil {
55+
log.Fatal(err)
56+
}
57+
}
58+
59+
return 0
60+
}
61+
62+
// Synopsis return help for commit command
63+
func (c RewriteCmd) Synopsis() string {
64+
return "Update git notes on history rewrite"
65+
}
66+

main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ func main() {
7171
UI: ui,
7272
}, nil
7373
},
74+
"rewrite": func() (cli.Command, error) {
75+
return &command.RewriteCmd{
76+
UI: ui,
77+
}, nil
78+
},
7479
}
7580

7681
exitStatus, err := c.Run()

metric/manager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func Process(interim bool, projPath ...string) (note.CommitNote, error) {
6868
return note.CommitNote{}, err
6969
}
7070

71-
if err := scm.CreateNote(note.Marshal(commitNote), project.NoteNameSpace); err != nil {
71+
if err := scm.CreateNote(note.Marshal(commitNote), project.NoteNameSpace, ""); err != nil {
7272
return note.CommitNote{}, err
7373
}
7474
if err := saveAndPurgeMetrics(gtmPath, metricMap, commitMap, readonlyMap); err != nil {

note/note.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ func UnMarshal(s string) (CommitNote, error) {
174174
}
175175

176176
default:
177-
return CommitNote{}, fmt.Errorf("Unable to unmarshal time logged, unknown version %s", version)
177+
continue // Ignore errors in syntax
178178
}
179179
}
180180
sort.Sort(sort.Reverse(FileByTime(files)))

scm/git.go

Lines changed: 89 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ func HeadCommit(wd ...string) (Commit, error) {
430430
}
431431
defer repo.Free()
432432

433-
headCommit, err := lookupHeadCommit(repo)
433+
headCommit, err := lookupCommit(repo)
434434
if err != nil {
435435
if err == ErrHeadUnborn {
436436
return commit, nil
@@ -457,13 +457,14 @@ func HeadCommit(wd ...string) (Commit, error) {
457457
}
458458

459459
// CreateNote creates a git note associated with the head commit
460-
func CreateNote(noteTxt string, nameSpace string, wd ...string) error {
460+
func CreateNote(noteTxt, nameSpace, commitHash string, wd ...string) error {
461461
defer util.Profile()()
462462

463463
var (
464464
repo *git.Repository
465465
err error
466466
prevNote *git.Note
467+
commit *git.Commit
467468
)
468469

469470
if len(wd) > 0 {
@@ -476,26 +477,33 @@ func CreateNote(noteTxt string, nameSpace string, wd ...string) error {
476477
}
477478
defer repo.Free()
478479

479-
headCommit, err := lookupHeadCommit(repo)
480+
if commitHash != "" {
481+
482+
}
483+
if commitHash != "" {
484+
commit, err = lookupCommit(repo, commitHash)
485+
} else {
486+
commit, err = lookupCommit(repo)
487+
}
480488
if err != nil {
481489
return err
482490
}
483491

484492
sig := &git.Signature{
485-
Name: headCommit.Author().Name,
486-
Email: headCommit.Author().Email,
487-
When: headCommit.Author().When,
493+
Name: commit.Author().Name,
494+
Email: commit.Author().Email,
495+
When: commit.Author().When,
488496
}
489497

490-
prevNote, err = repo.Notes.Read("refs/notes/"+nameSpace, headCommit.Id())
498+
prevNote, err = repo.Notes.Read("refs/notes/"+nameSpace, commit.Id())
491499

492500
if prevNote != nil {
493501
noteTxt += "\n" + prevNote.Message()
494502
if err := repo.Notes.Remove(
495503
"refs/notes/"+nameSpace,
496504
prevNote.Author(),
497505
prevNote.Committer(),
498-
headCommit.Id()); err != nil {
506+
commit.Id()); err != nil {
499507
return err
500508
}
501509

@@ -504,11 +512,45 @@ func CreateNote(noteTxt string, nameSpace string, wd ...string) error {
504512
}
505513
}
506514

507-
_, err = repo.Notes.Create("refs/notes/"+nameSpace, sig, sig, headCommit.Id(), noteTxt, false)
515+
516+
_, err = repo.Notes.Create("refs/notes/"+nameSpace, sig, sig, commit.Id(), noteTxt, false)
508517

509518
return err
510519
}
511520

521+
func RemoveNote(nameSpace, commitHash string, wd ...string) error {
522+
var (
523+
repo *git.Repository
524+
err error
525+
commit *git.Commit
526+
)
527+
528+
if len(wd) > 0 {
529+
repo, err = openRepository(wd[0])
530+
} else {
531+
repo, err = openRepository()
532+
}
533+
if err != nil {
534+
return err
535+
}
536+
defer repo.Free()
537+
538+
commit, err = lookupCommit(repo, commitHash)
539+
540+
if err != nil {
541+
return err
542+
}
543+
544+
sig := &git.Signature{
545+
Name: commit.Author().Name,
546+
Email: commit.Author().Email,
547+
When: commit.Author().When,
548+
}
549+
550+
err = repo.Notes.Remove("refs/notes/"+nameSpace, sig, sig, commit.Id())
551+
return err
552+
}
553+
512554
// CommitNote contains a git note's details
513555
type CommitNote struct {
514556
ID string
@@ -611,6 +653,19 @@ func ReadNote(commitID string, nameSpace string, calcStats bool, wd ...string) (
611653
}, nil
612654
}
613655

656+
func RewriteNote(oldHash, newHash, nameSpace string, wd ...string) error {
657+
oldNote, err := ReadNote(oldHash, nameSpace, true, wd...)
658+
if err != nil {
659+
return err
660+
}
661+
fmt.Println(oldNote.Note)
662+
err = CreateNote(oldNote.Note, nameSpace, newHash, wd...)
663+
if err != nil {
664+
return err
665+
}
666+
return RemoveNote(nameSpace, oldHash, wd...)
667+
}
668+
614669
// ConfigSet persists git configuration settings
615670
func ConfigSet(settings map[string]string, wd ...string) error {
616671
var (
@@ -984,23 +1039,34 @@ var (
9841039
ErrHeadUnborn = errors.New("Head commit not found")
9851040
)
9861041

987-
func lookupHeadCommit(repo *git.Repository) (*git.Commit, error) {
988-
989-
headUnborn, err := repo.IsHeadUnborn()
990-
if err != nil {
991-
return nil, err
992-
}
993-
if headUnborn {
994-
return nil, ErrHeadUnborn
995-
}
1042+
func lookupCommit(repo *git.Repository, hash ...string) (*git.Commit, error) {
1043+
var (
1044+
oid *git.Oid
1045+
err error
1046+
)
1047+
if len(hash) > 0 {
1048+
oid, err = git.NewOid(hash[0])
1049+
if err != nil {
1050+
return nil, err
1051+
}
1052+
} else {
1053+
headUnborn, err := repo.IsHeadUnborn()
1054+
if err != nil {
1055+
return nil, err
1056+
}
1057+
if headUnborn {
1058+
return nil, ErrHeadUnborn
1059+
}
9961060

997-
headRef, err := repo.Head()
998-
if err != nil {
999-
return nil, err
1061+
headRef, err := repo.Head()
1062+
if err != nil {
1063+
return nil, err
1064+
}
1065+
defer headRef.Free()
1066+
oid = headRef.Target()
10001067
}
1001-
defer headRef.Free()
10021068

1003-
commit, err := repo.LookupCommit(headRef.Target())
1069+
commit, err := repo.LookupCommit(oid)
10041070
if err != nil {
10051071
return nil, err
10061072
}

0 commit comments

Comments
 (0)