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

formatter.v1 imports gojsondiff from master #20

Open
gavv opened this issue Mar 28, 2017 · 5 comments
Open

formatter.v1 imports gojsondiff from master #20

gavv opened this issue Mar 28, 2017 · 5 comments

Comments

@gavv
Copy link
Contributor

gavv commented Mar 28, 2017

Hi,

It seems that current master is incompatible with v1, and they should not be used together. However, formatter.v1 imports gojsondiff from master, which causes problems.

Here is an example of a problem import: https://github.com/yudai/gojsondiff/blob/master/formatter/ascii.go#L9.

This example compiles well:

package main

import (
	"github.com/yudai/gojsondiff"
	"github.com/yudai/gojsondiff/formatter"
)

func main() {
	var d gojsondiff.Diff
	c := formatter.AsciiFormatterConfig{}
	f := formatter.NewAsciiFormatter(nil, c)
	f.Format(d)
}

But this one fails to compile:

package main

import (
	"gopkg.in/yudai/gojsondiff.v1"
	"gopkg.in/yudai/gojsondiff.v1/formatter"
)

func main() {
	var d gojsondiff.Diff
	c := formatter.AsciiFormatterConfig{}
	f := formatter.NewAsciiFormatter(nil, c)
	f.Format(d)
}

With the following error:

# command-line-arguments
./gjd.go:14: cannot use d (type "gopkg.in/yudai/gojsondiff.v1".Diff)
    as type "github.com/yudai/gojsondiff".Diff in argument to f.Format: 
      "gopkg.in/yudai/gojsondiff.v1".Diff does not implement
          "github.com/yudai/gojsondiff".Diff (wrong type for Deltas method)
                have Deltas() []"gopkg.in/yudai/gojsondiff.v1".Delta
                want Deltas() []"github.com/yudai/gojsondiff".Delta
@gavv
Copy link
Contributor Author

gavv commented Mar 28, 2017

I'm not sure what is the best way to fix this. One approach I know is the following:

  • Use version branches instead of version tags. For example, replace v1.0.0 tag with the v1 branch.
  • When a new stable branch is created, rewrite import URLs from github.com/yudai/gojsondiff to gopkg.in/yudai/gojsondiff.v1. It may be done using sed or gomove.

This is a bit tedious, but should work.

@yudai
Copy link
Owner

yudai commented Mar 29, 2017

Thanks for the report.

It seems that gopkg.in doesn't handle sub-packages well.
However, I don't feel like rewriting import paths is a good idea. I don't want to add something just relies on gopkg.in.
I rather want users to simply pin a commit ID in their package managers such as glide.

@GAAV you don't want to use a package manager for some reason?

I don't want to break your library again and again, so thinking what's the best way.

@gavv
Copy link
Contributor Author

gavv commented Mar 30, 2017

Vendoring is a good thing, but I think it should be done in applications, not in libraries.

If every library would vendor all its dependencies (recursively!), we'll get lots of duplicated dependencies. For example, gojsondiff vendors ginkgo and gomega which may be used by httpexpect users, and so will be duplicated.

I prefer the approach when libraries provide stable branches and rely on stable branches of their dependencies, and it's up to applications to vendor them all.

With this scheme, there is no duplication, and the application developer controls updates, which is very important. For example, if a security fix is released for a library foo, there is no need to wait when all libraries that use foo will update their vendored copy of foo. The application developer can just apply the fix immediately because (s)he controls the vendoring.

Actually, the approach of creating a stable branch for every major release is not new and is used for ages outside the Go ecosystem.

I understand the reasons to avoid hardcoding gopkg.in paths. However, if you want a stable branch in Go, you need to choose some way to change import paths. For example you can just create new repos, e.g. gojsondiff2, gojsondiff3, etc. The advantage of gopkg.in is that managing branches is easier than managing repos. After all, you already hardcode github.com paths, and gopkg.in is just another service.

That was some general thoughts about vendoring and versioning in Go. But well, I don't mind vendoring gojsondiff in httpexpect if you'll choose not to provide a stable branch. Anyway, I suggest to document gojsondiff versioning scheme in README.

@yudai
Copy link
Owner

yudai commented May 4, 2017

Maybe it's better to move formatter to the main package? let me see...

@gavv
Copy link
Contributor Author

gavv commented May 6, 2017

Sorry, I was wrong in the assumption that indirect dependencies vendored multiple times are duplicated. Instead, Go package managers flatten all nested vendor directories and every package is used exactly once. Therefore, my arguments related to the package duplication don't apply.

However, employing vendoring in libraries is problematic with flattening too. Problems will arise when different libraries vendor different incompatible versions of the same package with the same import path. Actually it seems to be even stronger argument to avoid vendoring in libraries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants