-
Notifications
You must be signed in to change notification settings - Fork 1.4k
graphqlbackend: Implement diff and reproducedDiff #47310
Changes from all commits
eeb32f4
11be359
dfadec2
1fb6d77
89b8231
e08efd0
88a9bd2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,11 +2,15 @@ package graphqlbackend | |
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
|
|
||
| "github.com/graph-gophers/graphql-go" | ||
| "github.com/graph-gophers/graphql-go/relay" | ||
| "github.com/sourcegraph/sourcegraph/internal/database" | ||
| "github.com/sourcegraph/sourcegraph/internal/gqlutil" | ||
|
|
||
| "github.com/hexops/gotextdiff" | ||
| "github.com/hexops/gotextdiff/myers" | ||
| ) | ||
|
|
||
| const siteConfigurationChangeKind = "SiteConfigurationChange" | ||
|
|
@@ -21,11 +25,6 @@ func (r SiteConfigurationChangeResolver) ID() graphql.ID { | |
| return marshalSiteConfigurationChangeID(r.siteConfig.ID) | ||
| } | ||
|
|
||
| // One line wrapper to be able to use in tests as well. | ||
| func marshalSiteConfigurationChangeID(id int32) graphql.ID { | ||
| return relay.MarshalID(siteConfigurationChangeKind, &id) | ||
| } | ||
|
|
||
| func (r SiteConfigurationChangeResolver) Author(ctx context.Context) (*UserResolver, error) { | ||
| if r.siteConfig.AuthorUserID == 0 { | ||
| return nil, nil | ||
|
|
@@ -39,17 +38,48 @@ func (r SiteConfigurationChangeResolver) Author(ctx context.Context) (*UserResol | |
| return user, nil | ||
| } | ||
|
|
||
| // TODO: Implement this. | ||
| func (r SiteConfigurationChangeResolver) Diff() string { | ||
| // TODO: We will do something like this, but for now return an empty string to not leak secrets | ||
| // until we have implemented redaction. | ||
| // | ||
| // if r.previousSiteConfig == nil { | ||
| // return "" | ||
| // } | ||
| func (r SiteConfigurationChangeResolver) ReproducedDiff() bool { | ||
| // If we were able to redact contents for both siteConfig and previousSiteConfig and store it in | ||
| // the DB, then we can generate a diff. | ||
| if r.siteConfig != nil { | ||
| // As a special case, if previousSiteConfig is nil (first entry in the DB) and we also have | ||
| // redactedContents available for this siteConfig, we can generate a diff (it will be all | ||
| // lines added). | ||
| if r.previousSiteConfig == nil && r.siteConfig.RedactedContents != "" { | ||
| return true | ||
| } | ||
|
|
||
| if r.siteConfig.RedactedContents != "" && r.previousSiteConfig.RedactedContents != "" { | ||
| return true | ||
| } | ||
| } | ||
|
|
||
| return false | ||
| } | ||
|
|
||
| func (r SiteConfigurationChangeResolver) Diff() *string { | ||
| if !r.ReproducedDiff() { | ||
| return nil | ||
| } | ||
|
|
||
| var prevID int32 | ||
| var prevRedactedContents string | ||
| if r.previousSiteConfig != nil { | ||
| prevID = r.previousSiteConfig.ID | ||
|
|
||
| // 🚨 SECURITY: This should always use "siteConfig.RedactedContents" and never | ||
| // "siteConfig.Contents" to generate the diff because we do not want to leak secrets in the | ||
| // diff. | ||
| prevRedactedContents = r.previousSiteConfig.RedactedContents | ||
| } | ||
|
|
||
| prettyID := func(id int32) string { return fmt.Sprintf("ID: %d", id) } | ||
|
|
||
| // We're not diffing a file, so set an empty string for the URI argument. | ||
| edits := myers.ComputeEdits("", prevRedactedContents, r.siteConfig.RedactedContents) | ||
| diff := fmt.Sprint(gotextdiff.ToUnified(prettyID(prevID), prettyID(r.siteConfig.ID), prevRedactedContents, edits)) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this require a call to
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it! (Might be a chance to open a tiny PR on
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great suggestion! PR filed: hexops/gotextdiff#3 |
||
|
|
||
| // return cmp.Diff(r.siteConfig.Contents, r.previousSiteConfig.Contents) | ||
| return "" | ||
| return &diff | ||
| } | ||
|
|
||
| func (r SiteConfigurationChangeResolver) CreatedAt() gqlutil.DateTime { | ||
|
|
@@ -59,3 +89,8 @@ func (r SiteConfigurationChangeResolver) CreatedAt() gqlutil.DateTime { | |
| func (r SiteConfigurationChangeResolver) UpdatedAt() gqlutil.DateTime { | ||
| return gqlutil.DateTime{Time: r.siteConfig.UpdatedAt} | ||
| } | ||
|
|
||
| // One line wrapper to be able to use in tests as well. | ||
| func marshalSiteConfigurationChangeID(id int32) graphql.ID { | ||
| return relay.MarshalID(siteConfigurationChangeKind, &id) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No change. Just moved it out of the way of the API methods and moved it all the way to the end of the file.