Relative package import in latest weekly

4,605 views
Skip to first unread message

Robert Johnstone

unread,
Mar 16, 2012, 12:33:13 PM3/16/12
to golang-nuts
Hello Everyone,

Is there a breakage in the latest weekly, or I have missed something?
The relative import worked in the previously weekly, but is broken
again in RC1.

can't load package: /home/robert/Code/go/src/pkg/javascriptcore/
base.go:7:8: local import "./strings" in non-local package

Thank-you,

Robert

minux

unread,
Mar 16, 2012, 12:40:35 PM3/16/12
to Robert Johnstone, golang-nuts
On Sat, Mar 17, 2012 at 12:33 AM, Robert Johnstone <r.w.jo...@gmail.com> wrote:
Is there a breakage in the latest weekly, or I have missed something?
The relative import worked in the previously weekly, but is broken
again in RC1.

can't load package: /home/robert/Code/go/src/pkg/javascriptcore/
base.go:7:8: local import "./strings" in non-local package
We intentionally disable this kind of local import in CL 5787055.
The rationale behind this decision could be found in the CL discussion.

Robert Johnstone

unread,
Mar 16, 2012, 2:34:45 PM3/16/12
to golang-nuts
Can you expand on the difference between local and non-local packages?

As I mentioned in the discussion linked to in the CL, I would like to
be able use relative imports when referring to sub-packages. The two
packages in question are inside my GOPATH.


On Mar 16, 12:40 pm, minux <minux...@gmail.com> wrote:
> We intentionally disable this kind of local import in CL
> 5787055<http://codereview.appspot.com/5787055>
> .

Kyle Lemons

unread,
Mar 16, 2012, 2:44:01 PM3/16/12
to Robert Johnstone, golang-nuts
It looks like only the package you're compiling (i.e. not any of its dependencies) can have relative imports.

andrey mirtchovski

unread,
Mar 16, 2012, 3:00:15 PM3/16/12
to Kyle Lemons, Robert Johnstone, golang-nuts
> It looks like only the package you're compiling (i.e. not any of its
> dependencies) can have relative imports.

that doesn't appear to be correct. i have a counter-example here that
compiles at tip just fine. trimmed down to basics, my usage is:

$ mkdir test test/test1 test/test2
$ cd test
$ cat > test1/test1.go
package test1
type T int
$ cat > test2/test2.go
package test2
import "./../test1"
type T2 test1.T
$ cat > test.go
package main
import (
"./test2"
"./test1"
"fmt"
)
func main() { var v test2.T2; var v1 test1.T; fmt.Printf("%T %T\n", v, v1) }
$ go build .
$ ./test
test2.T2 test1.T
$

yy

unread,
Mar 16, 2012, 3:05:47 PM3/16/12
to Robert Johnstone, golang-nuts
2012/3/16 Robert Johnstone <r.w.jo...@gmail.com>:

> Can you expand on the difference between local and non-local packages?
>
> As I mentioned in the discussion linked to in the CL, I would like to
> be able use relative imports when referring to sub-packages.  The two
> packages in question are inside my GOPATH.

This is precisely what has been disabled.

If I understood the rationale behind the change, packages imported
using relative paths were being re-built every time, instead of using
the installed package. Relative paths have the problem that you need
to know what they are relative to. They are less portable. So, to
avoid that people use them, they were disabled. However, they still
work when used by files that you build outside of GOPATH.

I'm still trying to figure out if there is any way to organize my code
so that I can distribute a snapshot of the repository and it can be
built by the go tool without having to modify any source file.


--
- yiyus || JGL .

Robert Johnstone

unread,
Mar 17, 2012, 2:14:24 PM3/17/12
to golang-nuts
I don't believe that is correct. I was informed by Rob Pike that the
go tool would support relative imports.

http://groups.google.com/group/golang-nuts/browse_thread/thread/1166adc653ea68ca/fbacef95e5f5848f?lnk=gst&q=relative+package#fbacef95e5f5848f

The issue discussed in the CL is using relative import paths to access
packages that are not inside the GOPATH. I believe that this is part
of the error message (i.e. the reference to non-local package). The
behaviour that the update was suppose to fix is using relative import
paths to access these outside packages. That is why I specifically
ask for someone to help clarify what is meant by a "non local
package". Since we still don't have an explanation, it is hard to
definitely determine whether this is a bug.

At the moment, I believe that the behaviour is a bug. Both packages
are inside my GOPATH, meaning that both are local. I'm accessing a
subpackage, which should be, to my mind, one of the (admittedly few)
uses cases for relative imports.

Finally, I'm consistently surprised by people arguing that relative
important paths are a problem because you need to know what they are
relative to. If I'm inside a package 'a', then import "./b" should be
equivalent to "a/b". It is not that hard, and programmers handle this
every day. Frankly, if this doesn't work it will be a huge pain.


On Mar 16, 12:05 pm, yy <yiyu....@gmail.com> wrote:
> 2012/3/16 Robert Johnstone <r.w.johnst...@gmail.com>:
> This is precisely what has been disabled.
>
> If I understood the rationale behind the change, packages imported
> usingrelativepaths were being re-built every time, instead of using
> the installedpackage.Relativepaths have the problem that you need
> to know what they arerelativeto. They are less portable. So, to

Ian Lance Taylor

unread,
Mar 18, 2012, 12:39:13 AM3/18/12
to Robert Johnstone, golang-nuts
Robert Johnstone <r.w.jo...@gmail.com> writes:

> Finally, I'm consistently surprised by people arguing that relative
> important paths are a problem because you need to know what they are
> relative to. If I'm inside a package 'a', then import "./b" should be
> equivalent to "a/b". It is not that hard, and programmers handle this
> every day. Frankly, if this doesn't work it will be a huge pain.

It's a bit more complicated in Go for a couple of reasons. The compiler
records the path to all imported packages, and the linker uses that
information when linking. That means that the linker has to be able to
find the import, even though the linker may be running in a different
directory. More seriously, because different packages are permitted to
have the same name in the package statement at the start of the file,
the compiler/linker distinguish different packages with the same name
based on the import path. That is, if one Go file imports "./b" and
another imports "a/b", those are considered to be two different packages
that happen to have the same name.

Ian

Robert Johnstone

unread,
Mar 18, 2012, 1:23:56 AM3/18/12
to golang-nuts
Thanks for the reply, but I'm afraid I still don't understand the
difficulty. If I'm in a directory (say a/b), and I change directory
(say ./c), the OS says normalizes the path. My new directory is a/b/
c, not ./c.

When doing an relative import, why doesn't the compiler normalize the
directory?

As I said previously, if I'm in package a, import "a/b" and import "./
b" should be equivalent. If the compiler only stores the normalized
paths in the object files, than the linker never has to worry about
relative imports.


On Mar 17, 10:39 pm, Ian Lance Taylor <i...@google.com> wrote:

Ian Lance Taylor

unread,
Mar 19, 2012, 12:21:51 PM3/19/12
to Robert Johnstone, golang-nuts
Robert Johnstone <r.w.jo...@gmail.com> writes:

> Thanks for the reply, but I'm afraid I still don't understand the
> difficulty. If I'm in a directory (say a/b), and I change directory
> (say ./c), the OS says normalizes the path. My new directory is a/b/
> c, not ./c.

Normalizing the path can be complex on Windows, when using an
automounter, or in the presence of symlinks when the symlink is the
preferred path. Turning a relative path into an absolute path is rarely
a good idea when communicating between programs that may be separated by
time, such as, in this case, the compiler and the linker.

Ian

yy

unread,
Mar 19, 2012, 2:30:07 PM3/19/12
to Ian Lance Taylor, Robert Johnstone, golang-nuts
2012/3/19 Ian Lance Taylor <ia...@google.com>:

Maybe I'm missing something, but I don't think it is so complex.

The path can perfectly be normalized by the go tool. The relative path
doesn't need to be turned into an absolute path, only to a full import
path. We already have the import path of the package, which is passed
as the argument to -p, we only need to pass the same argument to -D.

I don't know about gcc, but the gc compiler and linker would not need
any change, just get the right arguments, which we already know well.

I think this patch should be enough (inlined, just 4 lines). I did not
do too many tests, and only in linux, but I don't think it should get
much more complex:


diff -r 160ec5506cb7 src/cmd/go/pkg.go
--- a/src/cmd/go/pkg.go Sat Mar 17 22:19:57 2012 -0700
+++ b/src/cmd/go/pkg.go Mon Mar 19 20:04:49 2012 +0100
@@ -291,7 +291,7 @@

// The localPrefix is the path we interpret ./ imports relative to.
// Synthesized main packages sometimes override this.
- p.localPrefix = dirToImportPath(p.Dir)
+ p.localPrefix = p.ImportPath

if err != nil {
p.Incomplete = true
@@ -351,6 +351,9 @@
if path == "C" {
continue
}
+ if !p.local && build.IsLocalImport(path) {
+ path = pathpkg.Join(p.ImportPath, path)
+ }
p1 := loadImport(path, p.Dir, stk, p.build.ImportPos[path])
if p1.local {
if !p.local && p.Error == nil {

Robert Johnstone

unread,
Mar 19, 2012, 4:11:49 PM3/19/12
to golang-nuts
Please don't take my analogy with directories so literally! If I'm
compiling package "a", than import "a/b" and import "./b" should be
equivalent. The relative import should be joined with the package
currently being compiled.

If relative package imports are not supported, it will be a barrier to
forking code.

Robert

Kyle Lemons

unread,
Mar 19, 2012, 4:42:35 PM3/19/12
to Robert Johnstone, golang-nuts
On Mon, Mar 19, 2012 at 1:11 PM, Robert Johnstone <r.w.jo...@gmail.com> wrote:
Please don't take my analogy with directories so literally!  If I'm
compiling package "a", than import "a/b" and import "./b" should be
equivalent.  The relative import should be joined with the package
currently being compiled.

If relative package imports are not supported, it will be a barrier to
forking code.

Hmm, let's see, where's my [citation needed] stamp?

But in all seriousness, I think the clarity gained by absolute import paths vastly outweighs the pain of writing a sed command to update them (note also that the sed command to update import paths is vastly more complicated if you could have multiple different relative imports of the same package).

John Asmuth

unread,
Mar 19, 2012, 4:56:51 PM3/19/12
to golan...@googlegroups.com
Am I missing something? Doesn't the go tool already do this?

Aram Hăvărneanu

unread,
Mar 19, 2012, 4:59:51 PM3/19/12
to Kyle Lemons, Robert Johnstone, golang-nuts
> note also
> that the sed command to update import paths is vastly more complicated if
> you could have multiple different relative imports of the same package

Yes, it might be non-obvious, but absolute import path are more portable.

--
Aram Hăvărneanu

John Asmuth

unread,
Mar 19, 2012, 5:01:15 PM3/19/12
to golan...@googlegroups.com
Yes, I was - can't do it within $GOPATH. Didn't read the thread carefully.

Robert Johnstone

unread,
Mar 19, 2012, 6:00:49 PM3/19/12
to golang-nuts
Hmmm, I feel like a [citation needed] stamp is needed to support you
assertion that writing sed commands to update package imports is
easier. I have a situation right now where using absolute imports
will cause me head-aches. Nothing that can't be fixed, but
difficulties nevertheless.

1) I'll emphasize this again. I want import "a/b" and import "./b" to
be equivalent when compiling package "a". There is no ambiguity here.

2) I want to be able to fork a repository.

3) I want to be able to push to or pull from a forked repository.

Disallowing relative imports break both #2 and #3 (well, you could
cherry-pick, but we've complicated what should be a simple process).
I really appreciate gofmt, but does the community really feel the need
to dictate how users organize their projects? Especially since
authors are free to ignore the feature?

It is a 4 line patch. Once. On the other side is forcing every
forked library to require an addition edit to correct import paths,
and complicating every push or pull.



On Mar 19, 4:42 pm, Kyle Lemons <kev...@google.com> wrote:
> On Mon, Mar 19, 2012 at 1:11 PM, Robert Johnstone

Aram Hăvărneanu

unread,
Mar 19, 2012, 6:10:39 PM3/19/12
to Robert Johnstone, golang-nuts
> 1) I'll emphasize this again.  I want import "a/b" and import "./b" to
> be equivalent when compiling package "a".  There is no ambiguity here.

There is an ambiguity when compiling c, if c imports both a and a/b.

> 2) I want to be able to fork a repository.
>
> 3) I want to be able to push to or pull from a forked repository.

Fork at the vcs level, by creating a new branch. Iff you decide you
want to diverge from upstream your package should get a new
import path anyway and packages that decide to use your version
need to be updated as well.

It probably takes less time to write a sed one-liner that changes the
import path than the time it took me to write this sentence.

> Disallowing relative imports break both #2 and #3 (well, you could
> cherry-pick, but we've complicated what should be a simple process).

Relative import paths break #1.

There's also an indirection mechanism that allows to create short
import paths, I'm not sure if it's documented or not.

--
Aram Hăvărneanu

Jan Mercl

unread,
Mar 19, 2012, 6:13:22 PM3/19/12
to golan...@googlegroups.com
On Monday, March 19, 2012 11:00:49 PM UTC+1, Robert Johnstone wrote:
Hmmm, I feel like a [citation needed] stamp is needed to support you
assertion that writing sed commands to update package imports is
easier.  I have a situation right now where using absolute imports
will cause me head-aches. Nothing that can't be fixed, but
difficulties nevertheless.

1) I'll emphasize this again.  I want import "a/b" and import "./b" to
be equivalent when compiling package "a".  There is no ambiguity here.

2) I want to be able to fork a repository.

3) I want to be able to push to or pull from a forked repository.

Disallowing relative imports break both #2 and #3 (well, you could
cherry-pick, but we've complicated what should be a simple process).
I really appreciate gofmt, but does the community really feel the need
to dictate how users organize their projects?  Especially since
authors are free to ignore the feature?

It is a 4 line patch.  Once.  On the other side is forcing every
forked library to require an addition edit to correct import paths,
and complicating every push or pull.

Coding in Go heavily since 2009, I've yet to figure out what are relative import paths good for. I'm forking repos, public repos I'm involved in are being occasionally forked too, I'm pushing, pulling, merging, ..., and never yet used/noticed a relative import. What am I doing wrong? ;-)

(Maintaining e.g. https://github.com/cznic)


yy

unread,
Mar 19, 2012, 7:36:05 PM3/19/12
to Jan Mercl, golan...@googlegroups.com
2012/3/19 Jan Mercl <0xj...@gmail.com>:

>
> Coding in Go heavily since 2009, I've yet to figure out what are relative
> import paths good for. I'm forking repos, public repos I'm involved in are
> being occasionally forked too, I'm pushing, pulling, merging, ..., and never
> yet used/noticed a relative import. What am I doing wrong? ;-)
>
> (Maintaining e.g. https://github.com/cznic)


You are doing nothing wrong, but that does not mean relative imports
are wrong. They can be useful.

For example, in the github.com/cznic/dns repository there are several
packages. Some of these packages import other packages from the same
repository. If those import paths were relative I could fork that
repository and it would be ready for the go tool, without any
modification. I could also make a tarball and build it with the go
tool from anywhere inside or outside of GOPATH, without touching
anything. You cannot do that now, you have to edit the code.

I think the original problem is that a repository without subpackes is
not location dependent, but as soon as you refactor some code in a
subpackage your location is fixed because of the import path. There
may be some better solution to this problem that using relative paths,
but I don't think sed is that solution.

Eg:

You have app1 and pkg1 in repo/, you can install app1 and pkg1 from
GOPATH and import repo/pkg1 from any other package. You can also go
build app1 and pkg1 from any arbitrary location, or go run app1.

At some moment you decide to refactor some common code from app1 and
pkg1 into pkg2. You would prefer to keep your code usable from any
location. The obvious solution is to import ../pkg2 instead of
repo/pkg2. But, if you do that, then pkg1 can no longer be built in
GOPATH. If, instead, you use an absolute path, you have lost all the
freedom you had to build or run from any location. How do you handle
this situation?

Kyle Lemons

unread,
Mar 19, 2012, 8:16:47 PM3/19/12
to yy, Jan Mercl, golan...@googlegroups.com
When I fork code, I check it out into the original path.  If I fork code that I don't intend to push back, I might well use its native path, but I'd prefer it to still call out to the original subpackages so that I don't have to maintain those too.  I see no issue with using absolute paths here.

Liigo Zhuang

unread,
Mar 19, 2012, 10:02:30 PM3/19/12
to Robert Johnstone, golang-nuts

+1 for relative import path. The compiler should do normalizing relative path, and it's not too headache.

If the current compiling pkg is x, then the import path "./y" should normalized as "x/y" (by the compiler).

Sanjay Menakuru

unread,
Mar 19, 2012, 10:39:45 PM3/19/12
to golan...@googlegroups.com, Robert Johnstone
Sorry, I don't understand what advantage you feel relative import paths have over absolute ones.

In your example with github.com/cznic/dns, all sub packages would simply have an import path of github.com/cznic/dns/{foo,bar,etc}.
What's the problem with this model? Does this break in your workflow?

Sanjay

kortschak

unread,
Mar 19, 2012, 10:55:53 PM3/19/12
to golan...@googlegroups.com
It's not a huge deal to write a fix that will sanely apply changes that do everything you want if you feel the changes required are extensive. The Go1Rename fix shows that it's trivial given the go fix API.

Robert Johnstone

unread,
Mar 20, 2012, 12:15:40 AM3/20/12
to golang-nuts
It helps when you have very tightly coupled packages. These packages
are meant to be used together, but the code is separated into
different name spaces to help with organization, documentation, etc.
A lot of the original criticism came because people where using
relative paths to import packages that lived outside of their GOPATH.
I cannot comment on that use case, as it is not something I ever used.

For my 2 cents (which does not seem to be amounting to much with the
community), relative paths are useful for acessing sub-packages. They
are perhaps useful for accessing the parent package. Without relative
imports, forking a repository that has multiple packages requires
extra work to fix the import paths. Pushing or pulling between
repositories also now involve extra work.

Robert Johnstone

unread,
Mar 20, 2012, 12:17:35 AM3/20/12
to golang-nuts
To avoid going around in circles, can you provide a concrete example
where relative imports would be detrimental?

Sanjay Menakuru

unread,
Mar 20, 2012, 1:03:46 AM3/20/12
to golan...@googlegroups.com
Without relative 
imports, forking a repository that has multiple packages requires 
extra work to fix the import paths.  Pushing or pulling between 
repositories also now involve extra work.

Wait, I'm confused, what extra work is there?
Like Kyle said above, if you don't intend to contribute back, you might as well leave it with the original path, so you can pull updates later. If you do intend to contribute back, you have to leave it with the original path. I still don't understand your use case.

I could probably offer better suggestions if I fully understand the issue you're having.

Sanjay

PS - Its not that I think relative imports are *detrimental*, its just that I think that they just complicate things for no reason. Ignoring the compiler issues, it becomes harder to grep for uses of a package, and moving source code around might cause things to break.

楚杰

unread,
Mar 20, 2012, 3:26:00 AM3/20/12
to golan...@googlegroups.com, Robert Johnstone
For example, I want to fork github.com/cznic/dns in github.com, then my fork will become github.com/glacjay/dns, and all import path need to be changed.

在 2012年3月20日星期二UTC+8上午10时39分45秒,Sanjay Menakuru写道:

yy

unread,
Mar 20, 2012, 4:53:36 AM3/20/12
to kortschak, golan...@googlegroups.com
2012/3/20 kortschak <dan.ko...@adelaide.edu.au>:

> It's not a huge deal to write a fix that will sanely apply changes that do
> everything you want if you feel the changes required are extensive. The
> Go1Rename fix shows that it's trivial given the go fix API.

I was replying to the question of what relative paths are good for.

Indeed, writing a fix is not a big deal, but applying it can be a
pain. How would you distribute your code in a tarball if it has
subpackages? Either you say in your README or somewhere else that the
source has to be extracted to a specific location inside GOPATH or you
need to apply a fix before building with the go tool.

It is fine for me if relative paths are not allowed, I can live with
it, but I find unfortunate creating subpackages introduce this
limitation. I will have to consider if I prefer to fix my code to a
location or live with some duplicated code.

André Moraes

unread,
Mar 20, 2012, 8:05:23 AM3/20/12
to golang-nuts
On Tue, Mar 20, 2012 at 1:15 AM, Robert Johnstone
<r.w.jo...@gmail.com> wrote:
> It helps when you have very tightly coupled packages.  These packages
> are meant to be used together, but the code is separated into
> different name spaces to help with organization, documentation, etc.

Go packages should be complete units (libraries) and not simple
namespace things, so If two packages should be used together they
should be the same.

> A lot of the original criticism came because people where using
> relative paths to import packages that lived outside of their GOPATH.
> I cannot comment on that use case, as it is not something I ever used.
>
> For my 2 cents (which does not seem to be amounting to much with the
> community), relative paths are useful for acessing sub-packages.  They
> are perhaps useful for accessing the parent package.  Without relative
> imports, forking a repository that has multiple packages requires
> extra work to fix the import paths.  Pushing or pulling between
> repositories also now involve extra work.

GOPATH:
src
github.com
user1
pkg1 --> import ( ../pkg2 )
pkg2 --> import ( ../../user2/pkg1
user2
pkg1

--
André Moraes
http://andredevchannel.blogspot.com/

yy

unread,
Mar 20, 2012, 9:14:58 AM3/20/12
to André Moraes, golang-nuts
2012/3/20 André Moraes <and...@gmail.com>:

> Go packages should be complete units (libraries) and not simple
> namespace things, so If two packages should be used together they
> should be the same.

There is an exception to this, and that is when some common code is
factored out. For example, the package
code.google.com/p/go.crypto/openpgp/errors is meant to be used by the
other packages in that directory. I would not consider such a package
a complete unit, but a subpackage, part of a bigger project.

If this package could be imported like "../errors" then I could build
the packages inside openpgp from anywhere. I can accept that I cannot
do this, but I'd like to hear a good reason of why this is worse than
having to edit the original code.

I find strange having to edit source files just to build a project
from a different location (I find even stranger that most people here
seem to be fine with it). Relative paths could easily fix this. If
relative paths are considered harmful then, fair enough, that's the
wrong approach. Maybe there is other, more elegant solution and maybe
not. But can we agree that, if possible, not having to attach the code
to a fixed location is a desirable property?


> GOPATH:
>  src
>      github.com
>         user1
>            pkg1 --> import ( ../pkg2 )
>            pkg2 --> import ( ../../user2/pkg1
>         user2
>            pkg1

What's your point? If this is the only concern, the go tool could
protect against relative paths escaping the current repository.

If the feeling against relative paths is so strong, why aren't they
completely removed? I'm sure we can find other solutions to compile
subpackages outside of GOPATH.

André Moraes

unread,
Mar 20, 2012, 9:45:52 AM3/20/12
to golang-nuts
> There is an exception to this, and that is when some common code is
> factored out. For example, the package
> code.google.com/p/go.crypto/openpgp/errors is meant to be used by the
> other packages in that directory. I would not consider such a package
> a complete unit, but a subpackage, part of a bigger project.

It is complete if we consider that it's purpose it to define errors
messages, it's a small purpuse but it's complete. But I agree that
"complete unit" dependes of how somebody see the purpose of the
package.

> If this package could be imported like "../errors" then I could build
> the packages inside openpgp from anywhere. I can accept that I cannot
> do this, but I'd like to hear a good reason of why this is worse than
> having to edit the original code.
>
> I find strange having to edit source files just to build a project
> from a different location (I find even stranger that most people here
> seem to be fine with it). Relative paths could easily fix this. If
> relative paths are considered harmful then, fair enough, that's the
> wrong approach. Maybe there is other, more elegant solution and maybe
> not. But can we agree that, if possible, not having to attach the code
> to a fixed location is a desirable property?

I think the NodeJS loading and search is a example of how things can
become complex with relative paths, even if you know how nodejs load
libraries you still waste time thinking about where modules are coming
from.

With Go, you just need to know the value of GOPATH.

You can have multiple GOPATH's and switching from one version of a
library to another is just a matter of GOPATH=/my/custom/path. Also in
POSIX systems ls can help with that.

> If the feeling against relative paths is so strong, why aren't they
> completely removed? I'm sure we can find other solutions to compile
> subpackages outside of GOPATH.

How?

yy

unread,
Mar 20, 2012, 10:24:08 AM3/20/12
to André Moraes, golang-nuts
2012/3/20 André Moraes <and...@gmail.com>:

>> If the feeling against relative paths is so strong, why aren't they
>> completely removed? I'm sure we can find other solutions to compile
>> subpackages outside of GOPATH.
>
> How?

For example, with a new build option:

$ cd $HOME/project1 # not in GOPATH
$ go build -D 'repo.com/user/project1 -> /home/user/project1' ./...

(the right part of -> may default to $PWD if omitted and, of course,
this option should not be allowed for the install command).

Only the go tool would have to be modified to make this work and,
taking into account this would allow to remove all the support for
relative paths (and its currently non-existing documentation), it may
be a simplification.

I'm sure there are other ways I have not thought about, probably better.

Robert Johnstone

unread,
Mar 20, 2012, 12:20:56 PM3/20/12
to golang-nuts
Please note that I am not advocating for that type of behaviour. A
more typical use-case might be:

GOPATH:
src
github.com
user1
pkg1 --> import "./subpkg"
subpkg
pkg2
subpkg --> import pkg2 ".." (and I'm not sure about
this one)
user2
pkg3 --> import "github.com/user1/pkg1

People seem to confuse the intent. The goal is not to allow users to
circumvent the GOPATH. I simply want import "./subpkg" to be
equivalent to import "github.com/user1/pkg1/subpkg" when I'm compiling
"github.com/user1/pkg1". The transformation should happen before the
compiler goes back to the file system to read data from the imported
package. I would be disappointed if this flexibility was denied
because of unspecified fears. Can you provided a concrete harm to you
or your code that would come from allowing this?

Robert Johnstone

unread,
Mar 20, 2012, 12:30:05 PM3/20/12
to golang-nuts
> You can have multiple GOPATH's and switching from one version of a
> library to another is just a matter of GOPATH=/my/custom/path. Also in
> POSIX systems ls can help with that.

I don't no NodeJS so I can not comment on that specifically. Can you
provide a concrete example with Go where relative import paths will
cause a problem?

> You can have multiple GOPATH's and switching from one version of a
> library to another is just a matter of GOPATH=/my/custom/path. Also in
> POSIX systems ls can help with that.

That does not help when working with forked packages.

Robert Johnstone

unread,
Mar 20, 2012, 12:32:41 PM3/20/12
to golang-nuts


On Mar 20, 1:03 am, Sanjay Menakuru <balasan...@gmail.com> wrote:
> Like Kyle said above, if you don't intend to contribute back, you might as
> well leave it with the original path, so you can pull updates later. If you
> do intend to contribute back, you have to leave it with the original path.
> I still don't understand your use case.

That is the entire point of a DVCS. I can fork github.org/user1/pkg1
to github.org/user2/pkg_blah. I can then push, pull, or both from the
new repository.

André Moraes

unread,
Mar 20, 2012, 12:35:15 PM3/20/12
to Robert Johnstone, golang-nuts
>
> People seem to confuse the intent.  The goal is not to allow users to
> circumvent the GOPATH.  I simply want import "./subpkg" to be
> equivalent to import "github.com/user1/pkg1/subpkg" when I'm compiling
> "github.com/user1/pkg1".  The transformation should happen before the
> compiler goes back to the file system to read data from the imported
> package.  I would be disappointed if this flexibility was denied
> because of unspecified fears.

> Can you provided a concrete harm to your code that would come from allowing this?
I can't think o any harm that "./my sub package" will have, but
allowing "./" and not "./../" don't look right (personal opinion).

If "../" are allowed then the import path will become very complex to
understand simply by looking at it, and in this case, i prefer
absolute paths over relative ones. (another personal opinion).

Now, a possible solution to your problem:

Import the complete path of your project (JavaScriptCore bindings if I
am not wrong).

In bitbucket.org/rj/javascriptcore-go/base.go
import "bitbucket.org/rj/javascriptcore-go/strings"

Then if somebody want's to contribute code with you they need to
install your project under they GOPATH folder and change it.

If somebody want's to fork your code and do some changes and never
submit that again, they can:
Just use your path and never push their changes
Just use your path and add their remote repository as a valid URL in
.hg/hgrc and push their changes.

I don't see any problem here.

André Moraes

unread,
Mar 20, 2012, 12:40:44 PM3/20/12
to Robert Johnstone, golang-nuts
> I don't no NodeJS so I can not comment on that specifically.  Can you
> provide a concrete example with Go where relative import paths will
> cause a problem?

import (
"../../.././pk1"
)

func main() { pkg1.SayHello() }

Can you guess, just by reading this what is pkg1?

import (
"example.com/repo.git/terminal/pkg1"
)

func main() { pkg1.SayHello() }


>
>> You can have multiple GOPATH's and switching from one version of a
>> library to another is just a matter of GOPATH=/my/custom/path. Also in
>> POSIX systems ls can help with that.
>
> That does not help when working with forked packages.

Yes it does, I forked a GLFW package made my own changes, sent pull
request and didn't had to change the examples packages of the original
author.

That allowed me to write "go test ./..." to test if my changes broke something.

Rodrigo Kochenburger

unread,
Mar 20, 2012, 12:44:44 PM3/20/12
to André Moraes, Robert Johnstone, golang-nuts
I think the question is why the hell would you write this:

import (
 "../../.././pk1"
)

!?!?

I think relative import is important, even if only for subpackages (ie. not alowing ..), but if the language tries to control all wrong usage of things, it will become to restrictive for sure.

Just my 2 cents.

Rodrigo Kochenburger


2012/3/20 André Moraes <and...@gmail.com>

André Moraes

unread,
Mar 20, 2012, 12:55:43 PM3/20/12
to Rodrigo Kochenburger, golang-nuts
2012/3/20 Rodrigo Kochenburger <div...@gmail.com>:

> I think the question is why the hell would you write this:
>
> import (
>  "../../.././pk1"
> )
>
> !?!?

If the language allows it then people could write and this will be
valid and everybody will need to live with the possibility of finding
such code someday.

>
> I think relative import is important, even if only for subpackages (ie. not
> alowing ..), but if the language tries to control all wrong usage of things,

Allowing "./" isn't too bad and it's probably the only valid use of
relative paths that I can see.

But considering that GOPATH can change from one env to another by just
calling GOPATH="/some/path/here" then the abscense of relative paths
don't make things too complicated.

Rodrigo Kochenburger

unread,
Mar 20, 2012, 1:19:19 PM3/20/12
to André Moraes, golang-nuts
IMHO, it sill does.

Changing GOPATH won't change the fact that all imports will be absolute, and considering that go get will store the package in a url-like path (github.com/user/repos), forking a repos would allow me to change all the imports. 

Also, if you have a local codebase in $GOPATH/src/some_package and you decide to push it to github then you'd have to rewrite all imports.Same thing if you decide to download a tarball of a snapshot/tag and unpack it in your gopath, if the path doesnt mimic what go get would have done, you'll have to fix it.

To me, forcing absolute imports is a PITA. Having dumb people overusing relative path is something I can deal with by simply not using a software that uses that strategy as it is probably a crap one.

Rodrigo Kochenburger



2012/3/20 André Moraes <and...@gmail.com>
2012/3/20 Rodrigo Kochenburger <div...@gmail.com>:

Rodrigo Kochenburger

unread,
Mar 20, 2012, 1:19:54 PM3/20/12
to André Moraes, golang-nuts
In the first sentence, s/allow/force/ ;)

Rodrigo Kochenburger



2012/3/20 Rodrigo Kochenburger <div...@gmail.com>

Robert W. Johnstone

unread,
Mar 20, 2012, 1:25:21 PM3/20/12
to André Moraes, golang-nuts
On Tue, Mar 20, 2012 at 12:40 PM, André Moraes <and...@gmail.com> wrote:
> import (
>  "../../.././pk1"
> )
>
> func main() { pkg1.SayHello() }
>
> Can you guess, just by reading this what is pkg1?

First, that is not a concrete example, because you've stripped away
all context. Certainly while editing a package, I should know the
name of the package. If I'm editing "example.com/repo.git/terminal',
I would have no trouble seeing that the import is error. If the
import was correct, I would have no trouble determining the actual
target. Anyone who can use the cd command on the command-line should
be able to handle a relative import.

Second, you've picked a pathological case. You might as well be
worried that I will cryptographically encrypt all the function names
in my package. (Don't tempt me. I've been meaning to find a use for
Go's native unicode identifiers...)

> Yes it does, I forked a GLFW package made my own changes, sent pull
> request and didn't had to change the examples packages of the original
> author.

Did you duplicate all of your dependencies? No? Fortunately you can
add multiple directories in your GOPATH. Oh wait, now I've also got a
copy of the original repository in the GOPATH, so I'll have a
conflict. Not a problem, I'll create a third directory, move my local
copy of the original repository there... I'm not saying you can not
make it work, I'm asking why this is suppose to be easier than using
relative import paths.

Complexity happens. It is dangerous to throw away a tool just because
you have not *personally* had a use for it yet.

Kyle Lemons

unread,
Mar 20, 2012, 2:11:42 PM3/20/12
to Robert Johnstone, golang-nuts
If you intend to push it back, check out the new repository to GOPATH/src/github.com/usr1/pkg1 and work with it there.  If you don't, then you can fix it in one line *if you don't allow relative imports* (untested):
go get -d github.org/user2/pkg_blah && find $(go list -f "{.Dir}" github.org/user2/pkg_blah) -name "*.go" -exec sed --inline 's|github.org/user1/pkg1|github.org/user2/pkg_blah|' {} \; && git ci -a -m "Package rename"

Note that you can also copy their source into your own repository and sed the import paths without fear that the reorganization will break the packages *if you don't allow relative imports*:

src/
  you/
    "base"
    util/
      "convert"
  them/
    "base"
    "errors"

(copying their code into your project)
src/
  you/
    "base"
    "them" (one sed command)
    util/
      "convert"
      "errors" (one mv and one sed command)
  them/
    "base"
    "errors"

Rodrigo Kochenburger

unread,
Mar 20, 2012, 2:14:45 PM3/20/12
to Kyle Lemons, Robert Johnstone, golang-nuts
Right, and having a bunch of people to gsub using sed or whatever every time they fork something is much easier, lol

Rodrigo Kochenburger

Robert Johnstone

unread,
Mar 20, 2012, 2:26:01 PM3/20/12
to golang-nuts
Hello Everyone,

I've not seen any comments in this thread by RSC, who authored
http://codereview.appspot.com/5787055, or other golang developers. It
therefore appears that the decision is what it is. I'll stop using
sub-packages as a tool to organize my code.

André Moraes

unread,
Mar 20, 2012, 2:28:23 PM3/20/12
to Robert Johnstone, golang-nuts
> Complexity happens.  It is dangerous to throw away a tool just because
> you have not *personally* had a use for it yet.

I am not throwing anything out because I don't have a use.

I have forked repos which I make changes,
I have local code that is private right now but I will publish it later,
I have a use for "./pkg" and for "../otherPackage"

I just think that the benefits of relative packages are reduced by
it's problems (in the long run).

And pathological cases can become common cases.

"Almost never happens" == "can happens sometimes"

I am not even on the core language team, I just exposed a different
point of view that should be considered, my opinion goes to the toilet
if Go-lang team et. all decide that it's wrong, I will not fork the
compiler just because I don't like "../../" :)

André Moraes

unread,
Mar 20, 2012, 2:31:04 PM3/20/12
to Robert Johnstone, golang-nuts
> I've not seen any comments in this thread by RSC, who authored
> http://codereview.appspot.com/5787055, or other golang developers.  It

You missed Ian's comment.

> therefore appears that the decision is what it is.  I'll stop using
> sub-packages as a tool to organize my code.

--
André Moraes
http://andredevchannel.blogspot.com/

Rodrigo Kochenburger

unread,
Mar 21, 2012, 11:11:01 AM3/21/12
to golan...@googlegroups.com, André Moraes
Also, just realized that after forking and doing a gsub to replace all the repository absolute path, if I want to send a patch or a pull request, I have to gsub it all back. It is a pain.

Kyle Lemons

unread,
Mar 21, 2012, 1:35:23 PM3/21/12
to Rodrigo Kochenburger, golan...@googlegroups.com, André Moraes
If you're intending to push back, check out the forked source in the unforked path.  No gsub required.  The only reason to put it in its own path is if you do NOT intend to send a pull request.

2012/3/21 Rodrigo Kochenburger <div...@gmail.com>

Robert Johnstone

unread,
Mar 22, 2012, 11:34:55 AM3/22/12
to golang-nuts
Just used sed to rewrite all of the relative imports in a package to
absolute paths. It seems that this trick works for both absolute and
relative imports...

Rodrigo Kochenburger

unread,
Mar 22, 2012, 1:18:09 PM3/22/12
to golan...@googlegroups.com, Rodrigo Kochenburger, André Moraes
I don't follow.

If I fork, for example, github.com/someuser/repos and then my repos address becomes github.com/divoxx/repos. If i want it to be able to compile and run the tests in my machine I have to update all refs to the old repos.

Then if I send a pull request, I need to make sure those changes are not included in the changeset, so I have to revert back to the old ref or do some clever branching/rebasing to not incude it.

Francisco Souza

unread,
Mar 22, 2012, 1:28:16 PM3/22/12
to Rodrigo Kochenburger, golan...@googlegroups.com, André Moraes
2012/3/22 Rodrigo Kochenburger <div...@gmail.com>

I don't follow.

If I fork, for example, github.com/someuser/repos and then my repos address becomes github.com/divoxx/repos. If i want it to be able to compile and run the tests in my machine I have to update all refs to the old repos.

Then if I send a pull request, I need to make sure those changes are not included in the changeset, so I have to revert back to the old ref or do some clever branching/rebasing to not incude it.

mkdir -p ${GOPATH}/src/github.com/someuser
cd ${GOPATH}/src/github.com/someuser
git clone git://github.com/someuser/repos.git
cd repos
git remote add fork g...@github.com:divoxx/repos.git
... # changes and commits
git push fork master

Send the pull request.

--
~f
Message has been deleted

Rodrigo Kochenburger

unread,
Mar 22, 2012, 1:34:07 PM3/22/12
to golan...@googlegroups.com, Rodrigo Kochenburger, André Moraes
Ok, that would work. It just feel weird that when cloning the repos you'd have to know the file structure you'd have to clone. Supposing I have a fork with a feature that haven't been merged back yet but people still want to use my fork.

I know there are a couples of way around this, it just doesn't feel right.


On Thursday, March 22, 2012 2:30:11 PM UTC-3, Peter Thrun wrote:
If I fork, for example, github.com/someuser/repos and then my repos address becomes github.com/divoxx/repos. If i want it to be able to compile and run the tests in my machine I have to update all refs to the old repos.

You don't need to update the refs.  Clone the code where the go tool expects to find it.  Here's an example assuming that $GOPATH is a single directory.

$ mkdir -p $GOPATH/src/github.com/​someuser
$ cd $GOPATH/src/github.com/​someuser
$ cd repos
$ go install
... edit .. test ... edit ...
$ git push origin master
Message has been deleted

Rodrigo Kochenburger

unread,
Mar 22, 2012, 1:43:09 PM3/22/12
to Peter Thrun, golan...@googlegroups.com, André Moraes
Of course they can use clones, but I have never forked a repository that I was forced to clone it into a specific directory with a specific different name :)

I'm not saying is not doable, it is just a PITA and feel really strange.
 
Rodrigo Kochenburger



2012/3/22 Peter Thrun <peter...@ymail.com>
Ok, that would work. It just feel weird that when cloning the repos you'd have to know the file structure you'd have to clone.

If you clone a repository, it seems likely that you want to edit the files. You need to know the structure to edit the files.

Supposing I have a fork with a feature that haven't been merged back yet but people still want to use my fork.

They can use git clone as in my previous example.

Message has been deleted

hash

unread,
Mar 22, 2012, 3:08:29 PM3/22/12
to golan...@googlegroups.com, Rodrigo Kochenburger, André Moraes
On Thursday, 22 March 2012 18:28:16 UTC+1, Francisco Souza wrote:
2012/3/22 Rodrigo Kochenburger <>

--
~f
 
Well and when someone forks github.com/divoxx/repos.​git it will not build.

Best way would be to somehow not have user name in the sources.

--
hash

Message has been deleted
Message has been deleted

hash

unread,
Mar 22, 2012, 5:31:36 PM3/22/12
to golan...@googlegroups.com
On Thursday, 22 March 2012 21:15:16 UTC+1, Peter Thrun wrote:
Well and when someone forks github.com/divoxx/repos.​git it will not build.

It wil build if the repo is cloned to the location expected by the go tool.  Try the suggestions from hash and me and see for yourself.

Yes, but when someone will use go get on forked repo, it can not build in case of subpackages.

I think that subpackages should be visible to master package just by its name not full import path, and only to master package, and master packages should not be includable in subpackages.

Kyle Lemons

unread,
Mar 22, 2012, 5:40:33 PM3/22/12
to hash, golan...@googlegroups.com
That logic is hard to get right and hard to explain and is incredibly nuanced.  By far the simplest thing is just to not use relative imports.  I've never found this burdensome. 

André Moraes

unread,
Mar 23, 2012, 7:46:14 AM3/23/12
to Rodrigo Kochenburger, golan...@googlegroups.com
2012/3/22 Rodrigo Kochenburger <div...@gmail.com>:

> I don't follow.
>
> If I fork, for example, github.com/someuser/repos and then my repos address
> becomes github.com/divoxx/repos. If i want it to be able to compile and run
> the tests in my machine I have to update all refs to the old repos.

No, You don't.

Solution one, use symlinks

go get github.com/divoxx/repos
mkdir -p $GOPATH/src/github.com/someuser
cd $GOPATH/src/github.com/someuser
ln -s $GOPATH/src/github.com/divoxx/repos

This way you use your forked code with the same path of the upstream code.

Solution two, use git remote

go get github.com/divoxx/repos
go get github.com/someuser/repos
cd $GOPATH/src/github.com/someuser/repos
git remote add myfork ssh://g...@github.com/divoxx/repos
git pull myfork master

This way you use your forked code with the same path of the upstream code.

Both ways work perfectly fine for me when working on somebody else code.

If, you need to use both your code and the remote code, you can set
two different GOPATH variables and switch between them (GOPATH=.... go
<name your command here>)

Or just use two different import paths, this one makes a lot of sense,
since your forked code will not need to be compatible with the
upstream, they should be loaded from different paths.

>
> Then if I send a pull request, I need to make sure those changes are not
> included in the changeset, so I have to revert back to the old ref or do
> some clever branching/rebasing to not incude it.

boredom...@gmail.com

unread,
Apr 17, 2012, 12:20:07 AM4/17/12
to golan...@googlegroups.com
On Tuesday, March 20, 2012 9:20:56 AM UTC-7, Robert Johnstone wrote:
People seem to confuse the intent.  The goal is not to allow users to
circumvent the GOPATH.  I simply want import "./subpkg" to be
equivalent to import "github.com/user1/pkg1/subpkg" when I'm compiling
"github.com/user1/pkg1". 

Coming in late to the thread, but this just bit me for the first time tonight. I can see the motivation for disallowing relative paths for package imports, but this really does make it inconvenient for a github-style fork-and-experiment workflow if a package has used subpackages.

The suggested workaround of "mimic the original file path" isn't always workable; in this case, I want to have the original path living there (so I can refer to it as I experiment on my forked copy).

I guess the takeaway from this is "don't use subpackages if you want to allow easy forking"... which is awfully disappointing. 

André Moraes

unread,
Apr 17, 2012, 8:35:02 AM4/17/12
to boredom...@gmail.com, golan...@googlegroups.com
On Tue, Apr 17, 2012 at 1:20 AM, ste...@crinklink.com
<boredom...@gmail.com> wrote:
> On Tuesday, March 20, 2012 9:20:56 AM UTC-7, Robert Johnstone wrote:
>>
>> People seem to confuse the intent.  The goal is not to allow users to
>> circumvent the GOPATH.  I simply want import "./subpkg" to be
>> equivalent to import "github.com/user1/pkg1/subpkg" when I'm compiling
>> "github.com/user1/pkg1".
>
>
> Coming in late to the thread, but this just bit me for the first time
> tonight. I can see the motivation for disallowing relative paths for package
> imports, but this really does make it inconvenient for a github-style
> fork-and-experiment workflow if a package has used subpackages.

How, I really can't see the point.

Git have branches, and with "git checkout -b yourbranch" you switch
your working copy.

The "go" tool sees only your working copy. You can have as may
branches/remote refs as you want and just switch them with "git
checkout".

>
> The suggested workaround of "mimic the original file path" isn't always
> workable; in this case, I want to have the original path living there (so I
> can refer to it as I experiment on my forked copy).

If you are only making some "experiments" just change your GOPATH and
point to the experimental tree. It's even better this way since you
would have more control over what is in it.

> I guess the takeaway from this is "don't use subpackages if you want to
> allow easy forking"... which is awfully disappointing.

No, this isn't the takeway. The takeway is: if forking is so important
that you can't change a env-var, then use makefiles and gc toolchain,
instead of "go tool". The compiler/linker allows you to do that.

Steven Johnson

unread,
Apr 17, 2012, 1:12:03 PM4/17/12
to André Moraes, "steven@cri...@google.com, golan...@googlegroups.com
>> The suggested workaround of "mimic the original file path" isn't always
>> workable; in this case, I want to have the original path living there (so I
>> can refer to it as I experiment on my forked copy).
>
> If you are only making some "experiments" just change your GOPATH and
> point to the experimental tree. It's even better this way since you
> would have more control over what is in it.

I'd be happy to change GOPATH to accomplish this but I don't quite see
how that will work (without also editing the files for change the
imports). Perhaps you could explain a bit further?

André Moraes

unread,
Apr 17, 2012, 2:30:56 PM4/17/12
to Steven Johnson, "steven@cri...@google.com, golan...@googlegroups.com
> I'd be happy to change GOPATH to accomplish this but I don't quite see
> how that will work (without also editing the files for change the
> imports). Perhaps you could explain a bit further?

GOPATH=/home/user/Stable
go get github.com/user/lib1
Now, use the upstream version of the library in your production app.

GOPATH=/home/user/Testing
go get github.com/user/lib1
cd $GOPATH/src/github.com/user/lib1
git add remote myrepo g...@github.com/otheruser/lib1
git pull myrepo master
Now use your version of the library in your experimental application

In both cases the import path in your .go files is the same. No need
to change anything in the code.

But when the go tool is running, it will load the packages from
different locations, since GOPATH would be different.

Steven Johnson

unread,
Apr 17, 2012, 2:46:01 PM4/17/12
to André Moraes, golan...@googlegroups.com
Hmm... yeah, I guess that will work, it just seems kinda fiddly and
complicated, especially for github users who are (generally) used to
being able to fork and experiment without this sort of additional
doctoring.

I'm not proposing that the Go import style needs to change, but github
is rather popular, and offering a simple cookbook approach to making
its default workflow mesh more easily would seem to be a good thing
for would-be Go experimenters.

Would it be possible to have a way to tell the go tool to remap an
import within a given tree (perhaps via the .go file approach that
someone else proposed)... e.g., for the examples below

go get github.com/user/lib1
go get github.com/otheruser/lib1

What if there was a config file of the form

github.com/otheruser/lib1/.go
IMPORTMAP "github.com/user/lib1" = "/path/to/local/otheruser/lib1"

?

I infer that this sort of "local config file" approach has been
considered and rejected, but it's not clear to me why; it seems like a
much simpler and cleaner solution to this sort of issue. (Again,
apologies for coming in late to this thread.)

2012/4/17 André Moraes <and...@gmail.com>:

Jan Mercl

unread,
Apr 17, 2012, 3:03:37 PM4/17/12
to golan...@googlegroups.com
If one forks a Go project consisting of several packages then the "internal" imports can be edited manually, once and forever, in a matter of minutes. Perhaps sed'ed in a matter of seconds. In every case IMO in less time than this thread already spent.

Steven Johnson

unread,
Apr 17, 2012, 3:12:05 PM4/17/12
to Jan Mercl, golan...@googlegroups.com
On Tue, Apr 17, 2012 at 12:03 PM, Jan Mercl <0xj...@gmail.com> wrote:
> If one forks a Go project consisting of several packages then the "internal" imports can be edited manually, once and forever, in a matter of minutes.

But I don't want to edit them "forever" -- the whole issue is that
they have to be edited once (to get things to build locally), but when
I push back to github, I can either (1) leave them edited to refer to
my fork [in which case, pulling the change back to the original source
of the fork means they have to be edited back], or (2) change them
back to the original source of the fork [in which case, my fork will
need re-editing locally every time I sync]. Both of these options are
workable, but neither very appealing.

André Moraes

unread,
Apr 17, 2012, 3:37:08 PM4/17/12
to Steven Johnson, golan...@googlegroups.com
> What if there was a config file of the form
>
>    github.com/otheruser/lib1/.go
>        IMPORTMAP "github.com/user/lib1" = "/path/to/local/otheruser/lib1"
>
> ?

The important thing for the go tool is to: "Be able to build a Go
program without writing config files".

If the package owner really wants to allow easy forking, he could
write makefiles for that purpose or use another build tool.
It may break when somebody tries to "go get" your package.

Jan Mercl

unread,
Apr 17, 2012, 3:45:22 PM4/17/12
to golan...@googlegroups.com
It has been already pointed out by others that if you intend to make pull request to the originating repo then you want to have the local clone starting in the same original import path(s). The complementary issue of publishing a (go get-able) fork is the one I've talked about in the previous post. Are you talking about the case when you want to both publish a go get enabled fork and being able to make pull requsts from that repo towards the forked-from tepo? That's not possible in the case of "intra" repo imports, fortunately that doesn't sound like a common scenario to me.

Steven Johnson

unread,
Apr 17, 2012, 4:01:51 PM4/17/12
to golan...@googlegroups.com
2012/4/17 André Moraes <and...@gmail.com>:

> The important thing for the go tool is to: "Be able to build a Go
> program without writing config files".

...which would be neatly solved if we had relative import paths,
right? <ducking>

> If the package owner really wants to allow easy forking, he could
> write makefiles for that purpose or use another build tool.

But given typical github workflows, that's equivalent to saying "If
you are interested in writing multi-contributor projects in Go using
Github, you can't use the go build tool without extra effort -- use
makefiles instead." Surely there's a friendlier approach.

On Tue, Apr 17, 2012 at 12:45 PM, Jan Mercl <0xj...@gmail.com> wrote:
> Are you talking about the case when you want to both publish a go get enabled fork and being able to
> make pull requsts from that repo towards the forked-from tepo? That's not possible in the case of "intra"
> repo imports, fortunately that doesn't sound like a common scenario to me.

It's *not* a common scenario currently... but then, it couldn't be,
since it's not currently possible with the combination of "go get" and
github fork/pull.

I assertion is that it would become a common scenario if it was a bit
less painful to combine the two.

André Moraes

unread,
Apr 17, 2012, 4:14:47 PM4/17/12
to Steven Johnson, golan...@googlegroups.com
> But given typical github workflows, that's equivalent to saying "If
> you are interested in writing multi-contributor projects in Go using
> Github, you can't use the go build tool without extra effort -- use
> makefiles instead." Surely there's a friendlier approach.

Maybe is just me, but when I decide to work on a Go project that isn't mine,
I first "go get" the upstream package and later add the fork using git
remote add ....

If the person wan'ts to first "go get" the forked repo and later add
the upstream then it's a problem.

Message has been deleted

rocky

unread,
Apr 1, 2013, 11:43:49 PM4/1/13
to golan...@googlegroups.com, Robert Johnstone
On Monday, March 19, 2012 12:21:51 PM UTC-4, Ian Lance Taylor wrote:
Robert Johnstone <r.w.jo...@gmail.com> writes:

> Thanks for the reply, but I'm afraid I still don't understand the
> difficulty.  If I'm in a directory (say a/b), and I change directory
> (say ./c), the OS says normalizes the path.  My new directory is a/b/
> c, not ./c.

Normalizing the path can be complex on Windows, when using an
automounter,

relative import is only used inter project and not intra project. I think it safe to say that projects are not likely to span filesystems.

I don't think anyone would complain if relative import were disallowed between filesystems. 

Backing up before going forward...

The basic idea behind relative import is that one can have simple access between parts of a module or submodule. Rather than make concrete the name, e.g "a" above, it is desirable to refer to it as ".". That way if I want to change my module from say "dbgr" to "realgud" (which by the way I just did), I don't have  to change the myriad of files that have inter-module access. Instead I just change the directory name. The two other things I like about relative import is that it is more secure -- I really don't want the system to go scanning paths for inter-module access. If you can't find "c" in this directory, abort!  Please don't find it somewhere else. And finally, relative imports facilitates building and running inside the source tree without installing. That saves a step in the development edit/run cycle. 

So if there were a way to ensure you can stay inside the same filesystem or disallow crossing filesystems, then the requirements of the linker/compiler and the users are satisfied; both parties are happy. (If not, personally I don't think it a big deal because it's not likely to be done. So I would be happy to put the burden on the programmer for enforcement or blame when something goes wrong. But this might be consistent with go's overall philosophy.)

or in the presence of symlinks when the symlink is the
preferred path.  


This is a more interesting case. As a somewhat artificial but concrete example, suppose I have emacs-24.3.tar.gz that untars to emacs-24.3. And although this doesn't really occur, let's say underneath that I have  terminal.go which refers to charset.go  So the problem as I understand it, is that if I were to write import "./charset", what would happen is that this would get normalized to "emacs-24.3/charset" rather than what is desired "emacs/charset" or possibly or "emacs24/charset". (I realize that only after installing you'd have the symlink, but let's forget that here. I would like to promote developing and running inside source tree or even installed tree.) 

One way I see can this easily handled is something like what Python does.  
One could have an "init" file (python uses __init__.py) or something like that in the directory that says, "hey, I want '.' under here to mean "emacs" or "emacs24". 

In the case that there are submodules contained in modules, the linker or compiler could process these 'init' files to create the full hierarchy. For example, under emacs-24.3 I might have a "lib" directory. If /tmp/emacs-24.3/lib/sha1.go contains import "./config.go", the "." here would expand to "emacs/lib". You could know to stop at "emacs" and not go to "/tmp" because the "init" file could also say, hey, I'm the top level of this package. Less good would be to put in  /tmp/emacs-24.3/lib/init, "hey, I'm emacs/lib" because I would like to promote DRY (Do not repeat yourself). Here we would like to avoid proliferating the name emacs everywhere which makes it harder to rename that and isn't really adding much benefit inside the 90 or so files that might contain that. 

Ideally, since lib -> lib, that is, no symlink or translation is needed, it would be nice if no "init" file were needed.

That said, I realize that go is now in a mode where major changes like this aren't contemplated. But I want to address the technical concerns, so that at such time what it is possible to contemplate changes it's not dismissed for technical reasons. 


 

Turning a relative path into an absolute path is rarely
a good idea when communicating between programs that may be separated by
time, such as, in this case, the compiler and the linker.


Right. So although that is a kind of normalization, perhaps it is not the kind of normalization that should be done here. Rather, a normalization something like that outlined above.  

Ian

Reply all
Reply to author
Forward
0 new messages