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

Add support for comment and label manifests. #1408

Merged
merged 2 commits into from
Oct 15, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 97 additions & 26 deletions cmd/pullrequest-init/disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ limitations under the License.
package main

import (
"bufio"
"encoding/json"
"fmt"
"io/ioutil"
"net/url"
"os"
Expand All @@ -40,6 +42,10 @@ import (

// Filenames for labels and statuses are URL encoded for safety.

const (
manifestPath = ".MANIFEST"
)

// ToDisk converts a PullRequest object to an on-disk representation at the specified path.
func ToDisk(pr *PullRequest, path string) error {
labelsPath := filepath.Join(path, "labels")
Expand Down Expand Up @@ -80,28 +86,54 @@ func ToDisk(pr *PullRequest, path string) error {
}

func commentsToDisk(path string, comments []*Comment) error {
// Create a manifest to keep track of the comments that existed when the
// resource was initialized. This is used to verify that a comment that
// doesn't exist on disk was actually deleted by the user and not newly
// created during upload.
f, err := os.Create(filepath.Join(path, manifestPath))
if err != nil {
return err
}
defer f.Close()
manifest := bufio.NewWriter(f)

for _, c := range comments {
commentPath := filepath.Join(path, strconv.FormatInt(c.ID, 10)+".json")
id := strconv.FormatInt(c.ID, 10)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this manifest intended to be human readable? Would json serializing or gob serializing make it easier to safely round trip, so we don't have to manually encode to text?

Copy link
Member Author

Choose a reason for hiding this comment

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

Great idea!

Manifests are not meant to be human readable. Switched to gob encoding.

commentPath := filepath.Join(path, id+".json")
b, err := json.Marshal(c)
if err != nil {
return err
}
if err := ioutil.WriteFile(commentPath, b, 0700); err != nil {
if err := ioutil.WriteFile(commentPath, b, 0600); err != nil {
return err
}
if _, err := manifest.WriteString(fmt.Sprintf("%s\n", id)); err != nil {
return err
}
}
return nil
return manifest.Flush()
}

func labelsToDisk(path string, labels []*Label) error {
f, err := os.Create(filepath.Join(path, manifestPath))
if err != nil {
return err
}
defer f.Close()
manifest := bufio.NewWriter(f)

for _, l := range labels {
name := url.QueryEscape(l.Text)
labelPath := filepath.Join(path, name)
if err := ioutil.WriteFile(labelPath, []byte{}, 0700); err != nil {
if err := ioutil.WriteFile(labelPath, []byte{}, 0600); err != nil {
return err
}
if _, err := manifest.WriteString(fmt.Sprintf("%s\n", l.Text)); err != nil {
return err
}

}
return nil
return manifest.Flush()
}

func statusToDisk(path string, statuses []*Status) error {
Expand All @@ -127,57 +159,81 @@ func refToDisk(name, path string, r *GitReference) error {
return ioutil.WriteFile(filepath.Join(path, name+".json"), b, 0700)
}

// Manifest is a list of sub-resources that exist within the PR resource to
// determine whether an item existed when the resource was initialized.
type Manifest map[string]bool

// FromDisk outputs a PullRequest object from an on-disk representation at the specified path.
func FromDisk(path string) (*PullRequest, error) {
func FromDisk(path string) (*PullRequest, map[string]Manifest, error) {
labelsPath := filepath.Join(path, "labels")
commentsPath := filepath.Join(path, "comments")
statusesPath := filepath.Join(path, "status")

pr := PullRequest{}
manifests := make(map[string]Manifest)

var err error
var manifest Manifest

// Start with comments
pr.Comments, err = commentsFromDisk(commentsPath)
pr.Comments, manifest, err = commentsFromDisk(commentsPath)
if err != nil {
return nil, err
return nil, nil, err
}
manifests["comments"] = manifest

// Now Labels
pr.Labels, err = labelsFromDisk(labelsPath)
pr.Labels, manifest, err = labelsFromDisk(labelsPath)
if err != nil {
return nil, err
return nil, nil, err
}
manifests["labels"] = manifest

// Now statuses
pr.Statuses, err = statusesFromDisk(statusesPath)
if err != nil {
return nil, err
return nil, nil, err
}

// Finally refs

pr.Base, err = refFromDisk(path, "base.json")
if err != nil {
return nil, err
return nil, nil, err
}
pr.Head, err = refFromDisk(path, "head.json")
if err != nil {
return nil, nil, err
}
return &pr, manifests, nil
}

func manifestFromDisk(path string) (map[string]bool, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()

out := make(map[string]bool)
s := bufio.NewScanner(f)
for s.Scan() {
out[s.Text()] = true
}
if s.Err() != nil {
return nil, err
}
return &pr, nil
return out, nil
}

func commentsFromDisk(path string) ([]*Comment, error) {
func commentsFromDisk(path string) ([]*Comment, Manifest, error) {
fis, err := ioutil.ReadDir(path)
if err != nil {
return nil, err
return nil, nil, err
}
comments := []*Comment{}
for _, fi := range fis {
if fi.Name() == manifestPath {
continue
}
b, err := ioutil.ReadFile(filepath.Join(path, fi.Name()))
if err != nil {
return nil, err
return nil, nil, err
}
comment := Comment{}
if err := json.Unmarshal(b, &comment); err != nil {
Expand All @@ -186,23 +242,38 @@ func commentsFromDisk(path string) ([]*Comment, error) {
}
comments = append(comments, &comment)
}
return comments, nil

manifest, err := manifestFromDisk(filepath.Join(path, manifestPath))
if err != nil {
return nil, nil, err
}

return comments, manifest, nil
}

func labelsFromDisk(path string) ([]*Label, error) {
func labelsFromDisk(path string) ([]*Label, Manifest, error) {
fis, err := ioutil.ReadDir(path)
if err != nil {
return nil, err
return nil, nil, err
}
labels := []*Label{}
for _, fi := range fis {
if fi.Name() == manifestPath {
continue
}
text, err := url.QueryUnescape(fi.Name())
if err != nil {
return nil, err
return nil, nil, err
}
labels = append(labels, &Label{Text: text})
}
return labels, nil

manifest, err := manifestFromDisk(filepath.Join(path, manifestPath))
if err != nil {
return nil, nil, err
}

return labels, manifest, nil
}

func statusesFromDisk(path string) ([]*Status, error) {
Expand Down
Loading