Skip to content
This repository was archived by the owner on Aug 24, 2024. It is now read-only.

Commit 28af51e

Browse files
authored
Merge pull request #5 from MichaelMure/migration3
Add migration3
2 parents e246349 + 3561cc9 commit 28af51e

File tree

129 files changed

+17120
-8
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+17120
-8
lines changed

go.mod

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@ go 1.14
55
require (
66
github.com/99designs/keyring v1.1.5
77
github.com/blang/semver v3.5.1+incompatible
8+
github.com/blevesearch/bleve v1.0.14
89
github.com/dustin/go-humanize v1.0.0
910
github.com/fatih/color v1.9.0
11+
github.com/go-git/go-billy/v5 v5.0.0
1012
github.com/go-git/go-git/v5 v5.2.0
1113
github.com/mattn/go-isatty v0.0.12 // indirect
1214
github.com/pkg/errors v0.9.1
1315
github.com/spf13/cobra v1.0.0
1416
github.com/stretchr/testify v1.6.1
17+
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073
18+
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57
1519
golang.org/x/text v0.3.3
1620
)

go.sum

Lines changed: 85 additions & 0 deletions
Large diffs are not rendered by default.

migration1/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ git-bug v0.7.0
44
Changes:
55
- Added functionality to delete bugs
66
- Added functionality to set the author of a bug
7+
- Exposed formatVersion of OperationPack
78

89
Usage: This version is used to migrate the legacyAuthor from older versions to the newer versions of git-bug.

migration1/after/identity/version.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import (
1515

1616
const formatVersion = 1
1717

18+
var ErrIncorrectIdentityFormatVersion = fmt.Errorf("unknown format version")
19+
1820
// Version is a complete set of information about an Identity at a point in time.
1921
type Version struct {
2022
// The lamport time at which this version become effective
@@ -102,7 +104,7 @@ func (v *Version) UnmarshalJSON(data []byte) error {
102104
}
103105

104106
if aux.FormatVersion != formatVersion {
105-
return fmt.Errorf("unknown format version %v", aux.FormatVersion)
107+
return ErrIncorrectIdentityFormatVersion
106108
}
107109

108110
v.time = aux.Time

migration1/migration1.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package migration1
33
import (
44
"fmt"
55

6+
"github.com/pkg/errors"
7+
68
afterbug "github.com/MichaelMure/git-bug-migration/migration1/after/bug"
79
afteridentity "github.com/MichaelMure/git-bug-migration/migration1/after/identity"
810
afterrepo "github.com/MichaelMure/git-bug-migration/migration1/after/repository"
@@ -28,7 +30,7 @@ func (m *Migration1) Run(repoPath string) error {
2830
func (m *Migration1) migrate(repo afterrepo.ClockedRepo) error {
2931
err := m.readIdentities(repo)
3032
if err != nil {
31-
fmt.Printf("Error while applying migration")
33+
fmt.Printf("Error while applying migration\n")
3234
// stop the migration
3335
return nil
3436
}
@@ -37,7 +39,7 @@ func (m *Migration1) migrate(repo afterrepo.ClockedRepo) error {
3739
for streamedBug := range afterbug.ReadAllLocal(repo) {
3840
if streamedBug.Err != nil {
3941
if streamedBug.Err != afterbug.ErrInvalidFormatVersion {
40-
fmt.Printf("Got error when reading bug: %q\n", streamedBug.Err)
42+
fmt.Printf("got error when reading bug, assuming data is already migrated: %q\n", streamedBug.Err)
4143
} else {
4244
fmt.Printf("skipping bug, already updated\n")
4345
}
@@ -77,9 +79,14 @@ func (m *Migration1) migrate(repo afterrepo.ClockedRepo) error {
7779

7880
func (m *Migration1) readIdentities(repo afterrepo.ClockedRepo) error {
7981
for streamedIdentity := range afteridentity.ReadAllLocal(repo) {
80-
if streamedIdentity.Err != nil {
81-
fmt.Printf("Got error when reading identity: %q", streamedIdentity.Err)
82-
return streamedIdentity.Err
82+
if err := streamedIdentity.Err; err != nil {
83+
if errors.Is(err, afteridentity.ErrIncorrectIdentityFormatVersion) {
84+
fmt.Print("skipping identity, already updated\n")
85+
continue
86+
} else {
87+
fmt.Printf("Got error when reading identity: %q", streamedIdentity.Err)
88+
return streamedIdentity.Err
89+
}
8390
}
8491
m.allIdentities = append(m.allIdentities, streamedIdentity.Identity)
8592
}

migration3/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
### Vendor Information
2+
git-bug 11f3991e2be17a5e0740c429f48961bfe468c23a
3+
4+
Changes:
5+
- Exposed formatVersion of OperationPack
6+
- Removed error wrapping for bug and identity decoding
7+
- Added custom error message for invalid formatVersion

migration3/after/bug/bug.go

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
// Package bug contains the bug data model and low-level related functions
2+
package bug
3+
4+
import (
5+
"fmt"
6+
7+
"github.com/MichaelMure/git-bug-migration/migration3/after/entity"
8+
"github.com/MichaelMure/git-bug-migration/migration3/after/entity/dag"
9+
"github.com/MichaelMure/git-bug-migration/migration3/after/identity"
10+
"github.com/MichaelMure/git-bug-migration/migration3/after/repository"
11+
)
12+
13+
var _ Interface = &Bug{}
14+
var _ entity.Interface = &Bug{}
15+
16+
// 1: original format
17+
// 2: no more legacy identities
18+
// 3: Ids are generated from the create operation serialized data instead of from the first git commit
19+
// 4: with DAG entity framework
20+
const formatVersion = 4
21+
22+
var def = dag.Definition{
23+
Typename: "bug",
24+
Namespace: "bugs",
25+
OperationUnmarshaler: operationUnmarshaller,
26+
FormatVersion: formatVersion,
27+
}
28+
29+
var ClockLoader = dag.ClockLoader(def)
30+
31+
// Bug hold the data of a bug thread, organized in a way close to
32+
// how it will be persisted inside Git. This is the data structure
33+
// used to merge two different version of the same Bug.
34+
type Bug struct {
35+
*dag.Entity
36+
}
37+
38+
// NewBug create a new Bug
39+
func NewBug() *Bug {
40+
return &Bug{
41+
Entity: dag.New(def),
42+
}
43+
}
44+
45+
// Read will read a bug from a repository
46+
func Read(repo repository.ClockedRepo, id entity.Id) (*Bug, error) {
47+
e, err := dag.Read(def, repo, identity.NewSimpleResolver(repo), id)
48+
if err != nil {
49+
return nil, err
50+
}
51+
return &Bug{Entity: e}, nil
52+
}
53+
54+
// ReadWithResolver will read a bug from its Id, with a custom identity.Resolver
55+
func ReadWithResolver(repo repository.ClockedRepo, identityResolver identity.Resolver, id entity.Id) (*Bug, error) {
56+
e, err := dag.Read(def, repo, identityResolver, id)
57+
if err != nil {
58+
return nil, err
59+
}
60+
return &Bug{Entity: e}, nil
61+
}
62+
63+
type StreamedBug struct {
64+
Bug *Bug
65+
Err error
66+
}
67+
68+
// ReadAll read and parse all local bugs
69+
func ReadAll(repo repository.ClockedRepo) <-chan StreamedBug {
70+
return readAll(repo, identity.NewSimpleResolver(repo))
71+
}
72+
73+
// ReadAllWithResolver read and parse all local bugs
74+
func ReadAllWithResolver(repo repository.ClockedRepo, identityResolver identity.Resolver) <-chan StreamedBug {
75+
return readAll(repo, identityResolver)
76+
}
77+
78+
// Read and parse all available bug with a given ref prefix
79+
func readAll(repo repository.ClockedRepo, identityResolver identity.Resolver) <-chan StreamedBug {
80+
out := make(chan StreamedBug)
81+
82+
go func() {
83+
defer close(out)
84+
85+
for streamedEntity := range dag.ReadAll(def, repo, identityResolver) {
86+
if streamedEntity.Err != nil {
87+
out <- StreamedBug{
88+
Err: streamedEntity.Err,
89+
}
90+
} else {
91+
out <- StreamedBug{
92+
Bug: &Bug{Entity: streamedEntity.Entity},
93+
}
94+
}
95+
}
96+
}()
97+
98+
return out
99+
}
100+
101+
// ListLocalIds list all the available local bug ids
102+
func ListLocalIds(repo repository.Repo) ([]entity.Id, error) {
103+
return dag.ListLocalIds(def, repo)
104+
}
105+
106+
// Validate check if the Bug data is valid
107+
func (bug *Bug) Validate() error {
108+
if err := bug.Entity.Validate(); err != nil {
109+
return err
110+
}
111+
112+
// The very first Op should be a CreateOp
113+
firstOp := bug.FirstOp()
114+
if firstOp == nil || firstOp.Type() != CreateOp {
115+
return fmt.Errorf("first operation should be a Create op")
116+
}
117+
118+
// Check that there is no more CreateOp op
119+
for i, op := range bug.Operations() {
120+
if i == 0 {
121+
continue
122+
}
123+
if op.Type() == CreateOp {
124+
return fmt.Errorf("only one Create op allowed")
125+
}
126+
}
127+
128+
return nil
129+
}
130+
131+
// Append add a new Operation to the Bug
132+
func (bug *Bug) Append(op Operation) {
133+
bug.Entity.Append(op)
134+
}
135+
136+
// Operations return the ordered operations
137+
func (bug *Bug) Operations() []Operation {
138+
source := bug.Entity.Operations()
139+
result := make([]Operation, len(source))
140+
for i, op := range source {
141+
result[i] = op.(Operation)
142+
}
143+
return result
144+
}
145+
146+
// Compile a bug in a easily usable snapshot
147+
func (bug *Bug) Compile() Snapshot {
148+
snap := Snapshot{
149+
id: bug.Id(),
150+
Status: OpenStatus,
151+
}
152+
153+
for _, op := range bug.Operations() {
154+
op.Apply(&snap)
155+
snap.Operations = append(snap.Operations, op)
156+
}
157+
158+
return snap
159+
}
160+
161+
// Lookup for the very first operation of the bug.
162+
// For a valid Bug, this operation should be a CreateOp
163+
func (bug *Bug) FirstOp() Operation {
164+
if fo := bug.Entity.FirstOp(); fo != nil {
165+
return fo.(Operation)
166+
}
167+
return nil
168+
}
169+
170+
// Lookup for the very last operation of the bug.
171+
// For a valid Bug, should never be nil
172+
func (bug *Bug) LastOp() Operation {
173+
if lo := bug.Entity.LastOp(); lo != nil {
174+
return lo.(Operation)
175+
}
176+
return nil
177+
}

migration3/after/bug/bug_actions.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package bug
2+
3+
import (
4+
"github.com/pkg/errors"
5+
6+
"github.com/MichaelMure/git-bug-migration/migration3/after/entity"
7+
"github.com/MichaelMure/git-bug-migration/migration3/after/entity/dag"
8+
"github.com/MichaelMure/git-bug-migration/migration3/after/identity"
9+
"github.com/MichaelMure/git-bug-migration/migration3/after/repository"
10+
)
11+
12+
// Fetch retrieve updates from a remote
13+
// This does not change the local bugs state
14+
func Fetch(repo repository.Repo, remote string) (string, error) {
15+
return dag.Fetch(def, repo, remote)
16+
}
17+
18+
// Push update a remote with the local changes
19+
func Push(repo repository.Repo, remote string) (string, error) {
20+
return dag.Push(def, repo, remote)
21+
}
22+
23+
// Pull will do a Fetch + MergeAll
24+
// This function will return an error if a merge fail
25+
func Pull(repo repository.ClockedRepo, remote string, author identity.Interface) error {
26+
_, err := Fetch(repo, remote)
27+
if err != nil {
28+
return err
29+
}
30+
31+
for merge := range MergeAll(repo, remote, author) {
32+
if merge.Err != nil {
33+
return merge.Err
34+
}
35+
if merge.Status == entity.MergeStatusInvalid {
36+
return errors.Errorf("merge failure: %s", merge.Reason)
37+
}
38+
}
39+
40+
return nil
41+
}
42+
43+
// MergeAll will merge all the available remote bug
44+
// Note: an author is necessary for the case where a merge commit is created, as this commit will
45+
// have an author and may be signed if a signing key is available.
46+
func MergeAll(repo repository.ClockedRepo, remote string, author identity.Interface) <-chan entity.MergeResult {
47+
// no caching for the merge, we load everything from git even if that means multiple
48+
// copy of the same entity in memory. The cache layer will intercept the results to
49+
// invalidate entities if necessary.
50+
identityResolver := identity.NewSimpleResolver(repo)
51+
52+
out := make(chan entity.MergeResult)
53+
54+
go func() {
55+
defer close(out)
56+
57+
results := dag.MergeAll(def, repo, identityResolver, remote, author)
58+
59+
// wrap the dag.Entity into a complete Bug
60+
for result := range results {
61+
result := result
62+
if result.Entity != nil {
63+
result.Entity = &Bug{
64+
Entity: result.Entity.(*dag.Entity),
65+
}
66+
}
67+
out <- result
68+
}
69+
}()
70+
71+
return out
72+
}
73+
74+
// RemoveBug will remove a local bug from its entity.Id
75+
func RemoveBug(repo repository.ClockedRepo, id entity.Id) error {
76+
return dag.Remove(def, repo, id)
77+
}

migration3/after/bug/comment.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package bug
2+
3+
import (
4+
"github.com/dustin/go-humanize"
5+
6+
"github.com/MichaelMure/git-bug-migration/migration3/after/entity"
7+
"github.com/MichaelMure/git-bug-migration/migration3/after/identity"
8+
"github.com/MichaelMure/git-bug-migration/migration3/after/repository"
9+
"github.com/MichaelMure/git-bug-migration/migration3/after/util/timestamp"
10+
)
11+
12+
// Comment represent a comment in a Bug
13+
type Comment struct {
14+
id entity.Id
15+
Author identity.Interface
16+
Message string
17+
Files []repository.Hash
18+
19+
// Creation time of the comment.
20+
// Should be used only for human display, never for ordering as we can't rely on it in a distributed system.
21+
UnixTime timestamp.Timestamp
22+
}
23+
24+
// Id return the Comment identifier
25+
func (c Comment) Id() entity.Id {
26+
if c.id == "" {
27+
// simply panic as it would be a coding error
28+
// (using an id of an identity not stored yet)
29+
panic("no id yet")
30+
}
31+
return c.id
32+
}
33+
34+
// FormatTimeRel format the UnixTime of the comment for human consumption
35+
func (c Comment) FormatTimeRel() string {
36+
return humanize.Time(c.UnixTime.Time())
37+
}
38+
39+
func (c Comment) FormatTime() string {
40+
return c.UnixTime.Time().Format("Mon Jan 2 15:04:05 2006 +0200")
41+
}
42+
43+
// Sign post method for gqlgen
44+
func (c Comment) IsAuthored() {}

0 commit comments

Comments
 (0)