Write writes the OperationPack in git, with zero, one or more parent commits. If the repository has a key pair able to sign (that is, with a private key), the resulting commit is signed with that key. Return the hash of the created commit.
(def Definition, repo repository.Repo, parentCommit ...repository.Hash)
| 84 | // If the repository has a key pair able to sign (that is, with a private key), the resulting commit is signed with that key. |
| 85 | // Return the hash of the created commit. |
| 86 | func (opp *operationPack) Write(def Definition, repo repository.Repo, parentCommit ...repository.Hash) (repository.Hash, error) { |
| 87 | if err := opp.Validate(); err != nil { |
| 88 | return "", err |
| 89 | } |
| 90 | |
| 91 | // For different reason, we store the clocks and format version directly in the git tree. |
| 92 | // Version has to be accessible before any attempt to decode to return early with a unique error. |
| 93 | // Clocks could possibly be stored in the git blob but it's nice to separate data and metadata, and |
| 94 | // we are storing something directly in the tree already so why not. |
| 95 | // |
| 96 | // To have a valid Tree, we point the "fake" entries to always the same value, the empty blob. |
| 97 | emptyBlobHash, err := repo.StoreData([]byte{}) |
| 98 | if err != nil { |
| 99 | return "", err |
| 100 | } |
| 101 | |
| 102 | // Write the Ops as a Git blob containing the serialized array of operations |
| 103 | data, err := json.Marshal(opp) |
| 104 | if err != nil { |
| 105 | return "", err |
| 106 | } |
| 107 | |
| 108 | // compute the Id while we have the serialized data |
| 109 | opp.id = entity.DeriveId(data) |
| 110 | |
| 111 | hash, err := repo.StoreData(data) |
| 112 | if err != nil { |
| 113 | return "", err |
| 114 | } |
| 115 | |
| 116 | // Make a Git tree referencing this blob and encoding the other values: |
| 117 | // - format version |
| 118 | // - clocks |
| 119 | // - extra data |
| 120 | tree := []repository.TreeEntry{ |
| 121 | {ObjectType: repository.Blob, Hash: emptyBlobHash, |
| 122 | Name: fmt.Sprintf(versionEntryPrefix+"%d", def.FormatVersion)}, |
| 123 | {ObjectType: repository.Blob, Hash: hash, |
| 124 | Name: opsEntryName}, |
| 125 | {ObjectType: repository.Blob, Hash: emptyBlobHash, |
| 126 | Name: fmt.Sprintf(editClockEntryPrefix+"%d", opp.EditTime)}, |
| 127 | } |
| 128 | if opp.CreateTime > 0 { |
| 129 | tree = append(tree, repository.TreeEntry{ |
| 130 | ObjectType: repository.Blob, |
| 131 | Hash: emptyBlobHash, |
| 132 | Name: fmt.Sprintf(createClockEntryPrefix+"%d", opp.CreateTime), |
| 133 | }) |
| 134 | } |
| 135 | if extraTree := opp.makeExtraTree(); len(extraTree) > 0 { |
| 136 | extraTreeHash, err := repo.StoreTree(extraTree) |
| 137 | if err != nil { |
| 138 | return "", err |
| 139 | } |
| 140 | tree = append(tree, repository.TreeEntry{ |
| 141 | ObjectType: repository.Tree, |
| 142 | Hash: extraTreeHash, |
| 143 | Name: extraEntryName, |