Right list?


(Erica Sadun) #1

Is this the right list to ask about enhancing the Swift Package PackageDescription? I'd like to add a Package
property to namespace packages by origin, and to add aliases in Swift for renaming imports.

More details here if you'd like to read further: http://ericasadun.com/2016/02/08/naming-your-swift-packages/
I'm skipping them now because I'm not yet sure I've arrived at the right email list.

Thanks in advance, -- Erica


(Daniel Dunbar) #2

swift-build-dev is the development list for work on the package manager (and llbuild).

The namespace discussion is definitely an interesting topic to bring up. One thing which is currently true is that you effectively have a two-level namespace, the Git URL which is how SwiftPM finds your package, and the module name. The Git URL effectively encodes the part you are using as an origin, but of course that doesn't suffice:
1. If/when we had some kind of global index.
2. For the purposes of general ambiguity, if there are two popular FooBar packages.
3. If you have a package tree that happens to have conflicts.

- Daniel

···

On Feb 19, 2016, at 12:00 PM, Erica Sadun via swift-dev <swift-dev@swift.org> wrote:

Is this the right list to ask about enhancing the Swift Package PackageDescription? I'd like to add a Package
property to namespace packages by origin, and to add aliases in Swift for renaming imports.

More details here if you'd like to read further: http://ericasadun.com/2016/02/08/naming-your-swift-packages/
I'm skipping them now because I'm not yet sure I've arrived at the right email list.

Thanks in advance, -- Erica
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


(Max Howell) #3

Yes, we should probably take this to swift-build-dev.

I'd like to add a Package property to namespace packages by origin,

Some namespacing will certainly be required, the sooner the better.

I was hoping to namespace with github username where possible, it’s mxcl’s PromiseKit after all.

and to add aliases in Swift for renaming imports.

With namespacing we probably wouldn’t need this solution, which would be more ideal, eg:

    import Foo

Now you have two Foo, so any package that uses both must be specific:

    import mxcl.Foo
    import erica.Foo

Provided they are compiled such that the build system knows the namespaces at all times, we should be good. It’s only the user who doesn’t need to know at all times.


(Kostiantyn Koval) #4

In my opinion adding an origin to a Manifest file won’t solve the problem for 100%.
There could be a situation when 2 person would specify the same origin. Example
    origin: “com.erica”

The Github, Bitbucket (and others) takes care of providing unique user and repo names.
Reusing those would be more secure in my opinion.
In that case we don’t need to add any parameter to Manifest file and follow more convention style approach

Best Regard, Kostiantyn

···

On 19 Feb 2016, at 21:00, Erica Sadun via swift-dev <swift-dev@swift.org> wrote:

Is this the right list to ask about enhancing the Swift Package PackageDescription? I'd like to add a Package
property to namespace packages by origin, and to add aliases in Swift for renaming imports.

More details here if you'd like to read further: http://ericasadun.com/2016/02/08/naming-your-swift-packages/
I'm skipping them now because I'm not yet sure I've arrived at the right email list.

Thanks in advance, -- Erica
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev


(Erica Sadun) #5

Following up on this.

I first brought this topic up on swift-dev, and was pointed to swift-build-dev.

Having spent considerable time messing up my Swift packages by giving them ridiculously obvious names like SwiftString and SwiftCollections, I realized that namespacing would be a solution for disambiguating conflicts. import SwiftString is insufficient when several packages are named SwiftString.

When you have two identically named packages, the module imports need to distinguish both the sources as well as references defined per package. Although SwiftPM finds packages using git URLs and module names, I do not believe that origin is addressable or usable. Plus, throughout the lifetime of a package, that origin could potentially move from, for example, GitHub to Bitbucket.

I suggest using some kind of origin key for differentiation. The simplest solutions for these include reverse domain names (basically a company/source identifier), git URLs (the current location of the repo), Github/Bitbucket user names (which are similar to a company/source identifier but more subject to updates over time).

Of these, I’d recommend reverse domain for the following reasons:

They are relatively short
They are already well established for Apple app distribution
They do not rely on a web address that may change should the repo move
They are less likely to conflict with user names across repo hosts
I’d imagine a package declaration that looks something like this:

import PackageDescription

let package = Package(
    name: "SwiftString"
    origin: "org.sadun"
)
In the case of name conflicts instead of importing SwiftString, you’d prefix an origin:

import org.sadun.SwiftString
import com.foobar.SwiftString
Ideally, you could further alias these to shorten symbol disambiguation:

import org.sadun.SwiftString as SadunStrings
import com.foobar.SwiftString as FoobarStrings

// Unique to only one package, no name conflict
uniqueMethod("Hello World")

// name collision disambiguation
SadunStrings.sharedMethod("Hello World")
I'm interested in hearing any feedback and thoughts about whether this is possible and what I could do to help further this idea.

···

On Feb 19, 2016, at 5:50 PM, Max Howell <max.howell@apple.com> wrote:

Yes, we should probably take this to swift-build-dev.

I'd like to add a Package property to namespace packages by origin,

Some namespacing will certainly be required, the sooner the better.
I was hoping to namespace with github username where possible, it’s mxcl’s PromiseKit after all.

and to add aliases in Swift for renaming imports.

With namespacing we probably wouldn’t need this solution, which would be more ideal, eg:

   import Foo

Now you have two Foo, so any package that uses both must be specific:

   import mxcl.Foo
   import erica.Foo

Provided they are compiled such that the build system knows the namespaces at all times, we should be good. It’s only the user who doesn’t need to know at all times.


(Max Howell) #6

I first brought this topic up on swift-dev, and was pointed to swift-build-dev.

Having spent considerable time messing up my Swift packages by giving them ridiculously obvious names like SwiftString and SwiftCollections, I realized that namespacing would be a solution for disambiguating conflicts. import SwiftString is insufficient when several packages are named SwiftString.

When you have two identically named packages, the module imports need to distinguish both the sources as well as references defined per package. Although SwiftPM finds packages using git URLs and module names, I do not believe that origin is addressable or usable. Plus, throughout the lifetime of a package, that origin could potentially move from, for example, GitHub to Bitbucket.

I suggest using some kind of origin key for differentiation. The simplest solutions for these include reverse domain names (basically a company/source identifier), git URLs (the current location of the repo), Github/Bitbucket user names (which are similar to a company/source identifier but more subject to updates over time).

Of these, I’d recommend reverse domain for the following reasons:

They are relatively short
They are already well established for Apple app distribution
They do not rely on a web address that may change should the repo move
They are less likely to conflict with user names across repo hosts
I’d imagine a package declaration that looks something like this:

import PackageDescription

let package = Package(
    name: "SwiftString"
    origin: "org.sadun"
)
In the case of name conflicts instead of importing SwiftString, you’d prefix an origin:

import org.sadun.SwiftString
import com.foobar.SwiftString
Ideally, you could further alias these to shorten symbol disambiguation:

import org.sadun.SwiftString as SadunStrings
import com.foobar.SwiftString as FoobarStrings

// Unique to only one package, no name conflict
uniqueMethod("Hello World")

// name collision disambiguation
SadunStrings.sharedMethod("Hello World")
I'm interested in hearing any feedback and thoughts about whether this is possible and what I could do to help further this idea.

I think you have the right approach for sure. We need to talk with Swift-core as this will require work in that arena and they will need to chime in.

Certainly I would like to encourage namespacing with GitHub usernames because:

1) The majority of iOS open source happens there nowadays
2) People think of eg. mxcl’s PromiseKit, and thus both `import mxcl.PromiseKit` is very clear and communicates that these projects have origins/owners/maintainers.

However certainly I wouldn’t advocate for a GitHub only namespacing system, I just like that it have some extra sugar. SwiftPM was deliberately designed to be distributed.

I’ve cc’d Joe Groff since he probably can say something, then I can have some meetings, or we can try to do it all on the lists and then get this proposal written up.


(Max Howell) #7

I’d imagine a package declaration that looks something like this:
import PackageDescription

let package = Package(
    name: "SwiftString"
    origin: "org.sadun”
)

I imagined not needing the origin, since a package has a URL.

A package’s URL is its unique ID.

Now I am aware that the manifest does not include its URL, so there is potential for badness here, so perhaps we should insist that the URL is in the Manifest.

I haven’t got all my rationale in a concrete form yet, but I’d rather that the URL is the ID and it is the responsibility of the package author to keep the URL accurate. Much like the web. People delete things on the web, they move things on the web. It is the responsibility of the tooling and the community to work around that.


(Daniel Dunbar) #8

Can you explain a little more about your motivation for this?

I understand that "SwiftString", as a package, may be something which is likely to conflict. It isn't however clear to me that most packages fall into that category, or that it is even desirable to support features that encourage it.

For packages like "libjpeg", "LLVM", "OpenGL", "ncurses", "zlib", it seems like having one global namespace is OK, and even useful. As a Python user, for example, I have never been bother that the Python package index is a global namespace.

Is part of your motivation that you expect a different usage of Packages in the Swift ecosystem? I can see how if the expectation is that there are a lot of micro-framework style packages for basic functionality (i.e., "CountedCollections" or "GraphAlgorithms") that maybe the usage patterns would lend themselves to more conflicts.

- Daniel

···

On Feb 26, 2016, at 9:30 AM, Erica Sadun via swift-build-dev <swift-build-dev@swift.org> wrote:

On Feb 19, 2016, at 5:50 PM, Max Howell <max.howell@apple.com <mailto:max.howell@apple.com>> wrote:

Yes, we should probably take this to swift-build-dev.

I'd like to add a Package property to namespace packages by origin,

Some namespacing will certainly be required, the sooner the better.
I was hoping to namespace with github username where possible, it’s mxcl’s PromiseKit after all.

and to add aliases in Swift for renaming imports.

With namespacing we probably wouldn’t need this solution, which would be more ideal, eg:

   import Foo

Now you have two Foo, so any package that uses both must be specific:

   import mxcl.Foo
   import erica.Foo

Provided they are compiled such that the build system knows the namespaces at all times, we should be good. It’s only the user who doesn’t need to know at all times.

Following up on this.

I first brought this topic up on swift-dev, and was pointed to swift-build-dev.

Having spent considerable time messing up my Swift packages by giving them ridiculously obvious names like SwiftString and SwiftCollections, I realized that namespacing would be a solution for disambiguating conflicts. import SwiftString is insufficient when several packages are named SwiftString.

When you have two identically named packages, the module imports need to distinguish both the sources as well as references defined per package. Although SwiftPM finds packages using git URLs and module names, I do not believe that origin is addressable or usable. Plus, throughout the lifetime of a package, that origin could potentially move from, for example, GitHub to Bitbucket.

I suggest using some kind of origin key for differentiation. The simplest solutions for these include reverse domain names (basically a company/source identifier), git URLs (the current location of the repo), Github/Bitbucket user names (which are similar to a company/source identifier but more subject to updates over time).

Of these, I’d recommend reverse domain for the following reasons:

They are relatively short
They are already well established for Apple app distribution
They do not rely on a web address that may change should the repo move
They are less likely to conflict with user names across repo hosts
I’d imagine a package declaration that looks something like this:

import PackageDescription

let package = Package(
    name: "SwiftString"
    origin: "org.sadun"
)
In the case of name conflicts instead of importing SwiftString, you’d prefix an origin:

import org.sadun.SwiftString
import com.foobar.SwiftString
Ideally, you could further alias these to shorten symbol disambiguation:

import org.sadun.SwiftString as SadunStrings
import com.foobar.SwiftString as FoobarStrings

// Unique to only one package, no name conflict
uniqueMethod("Hello World")

// name collision disambiguation
SadunStrings.sharedMethod("Hello World")
I'm interested in hearing any feedback and thoughts about whether this is possible and what I could do to help further this idea.
_______________________________________________
swift-build-dev mailing list
swift-build-dev@swift.org <mailto:swift-build-dev@swift.org>
https://lists.swift.org/mailman/listinfo/swift-build-dev


(Joe Groff) #9

Usernames strike me as too short to serve as a universal discriminator by themselves, and as you noted, tie the system to a specific service. Reverse-domain is certainly more precedented. I'm jumping into this conversation in the middle, so pardon me if this has already been discussed, but could the package manifest take responsibility for mapping global package identifiers to their source-level module names? That would let you say:

let dependencies = [
  "SadunString": "org.sadun.SwiftString",
  "FoobarStrings": "com.foobar.SwiftString"
]

and would give users some leeway to change their module references, should their dependencies end up forked or vendored.

-Joe

···

On Feb 26, 2016, at 10:30 AM, Max Howell <max.howell@apple.com> wrote:

I first brought this topic up on swift-dev, and was pointed to swift-build-dev.

Having spent considerable time messing up my Swift packages by giving them ridiculously obvious names like SwiftString and SwiftCollections, I realized that namespacing would be a solution for disambiguating conflicts. import SwiftString is insufficient when several packages are named SwiftString.

When you have two identically named packages, the module imports need to distinguish both the sources as well as references defined per package. Although SwiftPM finds packages using git URLs and module names, I do not believe that origin is addressable or usable. Plus, throughout the lifetime of a package, that origin could potentially move from, for example, GitHub to Bitbucket.

I suggest using some kind of origin key for differentiation. The simplest solutions for these include reverse domain names (basically a company/source identifier), git URLs (the current location of the repo), Github/Bitbucket user names (which are similar to a company/source identifier but more subject to updates over time).

Of these, I’d recommend reverse domain for the following reasons:

They are relatively short
They are already well established for Apple app distribution
They do not rely on a web address that may change should the repo move
They are less likely to conflict with user names across repo hosts
I’d imagine a package declaration that looks something like this:

import PackageDescription

let package = Package(
    name: "SwiftString"
    origin: "org.sadun"
)
In the case of name conflicts instead of importing SwiftString, you’d prefix an origin:

import org.sadun.SwiftString
import com.foobar.SwiftString
Ideally, you could further alias these to shorten symbol disambiguation:

import org.sadun.SwiftString as SadunStrings
import com.foobar.SwiftString as FoobarStrings

// Unique to only one package, no name conflict
uniqueMethod("Hello World")

// name collision disambiguation
SadunStrings.sharedMethod("Hello World")
I'm interested in hearing any feedback and thoughts about whether this is possible and what I could do to help further this idea.

I think you have the right approach for sure. We need to talk with Swift-core as this will require work in that arena and they will need to chime in.

Certainly I would like to encourage namespacing with GitHub usernames because:

1) The majority of iOS open source happens there nowadays
2) People think of eg. mxcl’s PromiseKit, and thus both `import mxcl.PromiseKit` is very clear and communicates that these projects have origins/owners/maintainers.

However certainly I wouldn’t advocate for a GitHub only namespacing system, I just like that it have some extra sugar. SwiftPM was deliberately designed to be distributed.

I’ve cc’d Joe Groff since he probably can say something, then I can have some meetings, or we can try to do it all on the lists and then get this proposal written up.


(Max Howell) #10

Can you explain a little more about your motivation for this?

I understand that "SwiftString", as a package, may be something which is likely to conflict. It isn't however clear to me that most packages fall into that category, or that it is even desirable to support features that encourage it.

I don’t mean to intercept Erica here, but I wanted to chime-in.

For me, my motivation is we don’t have a single index, so it is quite likely that module names will collide at some point.

We need some solution for this. Originally I was thinking, well lets allow overrides for module-names, which is still an option, but it is not as simple as I originally hoped since any packages that depend on that module in a deep tree will require either:

1) Swift-the-language support for the rename.
2) Or a preprocessor step in the Package Manager that renames module imports in affected packages.

Namespaces are more elegant, especially if by default you don’t have to care. Packages would only have to care if they import two modules with the same name, and this would be discovered by the package author, not by the end-user who just happened to depend on the wrong combination of packages.

Also, personally, I want people to call their packages “StringExtensions”. Currently the iOS development world is filled with silly names for packages, and this partly happens because the good names are already taken. People would instead say “Daniel Dunbar’s String Extensions” and for me, that is what the package should be called.

For packages like "libjpeg", "LLVM", "OpenGL", "ncurses", "zlib", it seems like having one global namespace is OK, and even useful. As a Python user, for example, I have never been bother that the Python package index is a global namespace.

Yes, this is separate (for me). And handled by module map packages.


(Max Howell) #11

Usernames strike me as too short to serve as a universal discriminator by themselves, and as you noted, tie the system to a specific service. Reverse-domain is certainly more precedented.

I imagined only using username when the package has a URL that is a github URL.

Really it would just be a convenience for:

    import com.github.mxcl.PromiseKit

I'm jumping into this conversation in the middle, so pardon me if this has already been discussed, but could the package manifest take responsibility for mapping global package identifiers to their source-level module names? That would let you say:

let dependencies = [
  "SadunString": "org.sadun.SwiftString",
  "FoobarStrings": "com.foobar.SwiftString"
]

and would give users some leeway to change their module references, should their dependencies end up forked or vendors.

Our long term goals include plans for “overrides” to allow users to say, for this module name, use this package URL. Yes. And probably we could roll that into this proposal.


(Erica Sadun) #12

Original post here: http://ericasadun.com/2016/02/08/naming-your-swift-packages/ and you really haven't missed much.

If you want to do it from the consumer end, then it becomes a lot simpler, without adding any specific origin information or adapting the package declaration. This is what it looks like now:
import PackageDescription
let package = Package (
    name: "myutility",
    dependencies: [
  .Package(url: "https://github.com/erica/SwiftString.git",
                 majorVersion: 1),
  .Package(url: "https://github.com/bob/SwiftString.git",
                 majorVersion: 1),
    ]
)
I'd imagine that you'd want to change it to look like this:
import PackageDescription
let package = Package (
    name: "myutility",
    dependencies: [
  .Package(url: "https://github.com/erica/SwiftString.git",
                 majorVersion: 1, localName: "SadunString"),
  .Package(url: "https://github.com/bob/SwiftString.git",
                 majorVersion: 1, localName: "BobString"),
    ]
)
If you leave off localName (or whatever it is called), it imports as the name declared in Package.name.

-- E

···

On Feb 26, 2016, at 11:40 AM, Joe Groff <jgroff@apple.com> wrote:

On Feb 26, 2016, at 10:30 AM, Max Howell <max.howell@apple.com <mailto:max.howell@apple.com>> wrote:

I first brought this topic up on swift-dev, and was pointed to swift-build-dev.

Having spent considerable time messing up my Swift packages by giving them ridiculously obvious names like SwiftString and SwiftCollections, I realized that namespacing would be a solution for disambiguating conflicts. import SwiftString is insufficient when several packages are named SwiftString.

When you have two identically named packages, the module imports need to distinguish both the sources as well as references defined per package. Although SwiftPM finds packages using git URLs and module names, I do not believe that origin is addressable or usable. Plus, throughout the lifetime of a package, that origin could potentially move from, for example, GitHub to Bitbucket.

I suggest using some kind of origin key for differentiation. The simplest solutions for these include reverse domain names (basically a company/source identifier), git URLs (the current location of the repo), Github/Bitbucket user names (which are similar to a company/source identifier but more subject to updates over time).

Of these, I’d recommend reverse domain for the following reasons:

They are relatively short
They are already well established for Apple app distribution
They do not rely on a web address that may change should the repo move
They are less likely to conflict with user names across repo hosts
I’d imagine a package declaration that looks something like this:

import PackageDescription

let package = Package(
    name: "SwiftString"
    origin: "org.sadun"
)
In the case of name conflicts instead of importing SwiftString, you’d prefix an origin:

import org.sadun.SwiftString
import com.foobar.SwiftString
Ideally, you could further alias these to shorten symbol disambiguation:

import org.sadun.SwiftString as SadunStrings
import com.foobar.SwiftString as FoobarStrings

// Unique to only one package, no name conflict
uniqueMethod("Hello World")

// name collision disambiguation
SadunStrings.sharedMethod("Hello World")
I'm interested in hearing any feedback and thoughts about whether this is possible and what I could do to help further this idea.

I think you have the right approach for sure. We need to talk with Swift-core as this will require work in that arena and they will need to chime in.

Certainly I would like to encourage namespacing with GitHub usernames because:

1) The majority of iOS open source happens there nowadays
2) People think of eg. mxcl’s PromiseKit, and thus both `import mxcl.PromiseKit` is very clear and communicates that these projects have origins/owners/maintainers.

However certainly I wouldn’t advocate for a GitHub only namespacing system, I just like that it have some extra sugar. SwiftPM was deliberately designed to be distributed.

I’ve cc’d Joe Groff since he probably can say something, then I can have some meetings, or we can try to do it all on the lists and then get this proposal written up.

Usernames strike me as too short to serve as a universal discriminator by themselves, and as you noted, tie the system to a specific service. Reverse-domain is certainly more precedented. I'm jumping into this conversation in the middle, so pardon me if this has already been discussed, but could the package manifest take responsibility for mapping global package identifiers to their source-level module names? That would let you say:

let dependencies = [
  "SadunString": "org.sadun.SwiftString",
  "FoobarStrings": "com.foobar.SwiftString"
]

and would give users some leeway to change their module references, should their dependencies end up forked or vendored.


(Erica Sadun) #13

I think names like "Daniel Dunbar's String Extensions" is great when talking in English about a specific extension but I think the actual name should be as simple and elegant as possible without overlapping with built-in keywords.

import String // bad, name conflict
import StringUtilities // good. simple, gets to the point, it will be very rare that you'll want to import several of these, but it may happen
import org.sadun.StringUtilities // I can live with this but I'd rather import with a custom name established in dependencies
import org.sadun.StringUtilities as SadunStrings // also okay, again, the custom name will be used and it's unique and short
import `Daniel Dunbar's String Extensions` // bad, especially when you have to reference it
import `Daniel Dunbar's String Extensions` as DunbarStrings// slight improvement but not much, it's ugly, clunky, etc.
import SadunStringUtilities // This is why we're trying to leave Cocoa behind. If we have to namespace stuff just to avoid conflicts, we've already lost

-- E

···

On Feb 26, 2016, at 3:27 PM, Max Howell <max.howell@apple.com> wrote:

Can you explain a little more about your motivation for this?

I understand that "SwiftString", as a package, may be something which is likely to conflict. It isn't however clear to me that most packages fall into that category, or that it is even desirable to support features that encourage it.

I don’t mean to intercept Erica here, but I wanted to chime-in.

For me, my motivation is we don’t have a single index, so it is quite likely that module names will collide at some point.

We need some solution for this. Originally I was thinking, well lets allow overrides for module-names, which is still an option, but it is not as simple as I originally hoped since any packages that depend on that module in a deep tree will require either:

1) Swift-the-language support for the rename.
2) Or a preprocessor step in the Package Manager that renames module imports in affected packages.

Namespaces are more elegant, especially if by default you don’t have to care. Packages would only have to care if they import two modules with the same name, and this would be discovered by the package author, not by the end-user who just happened to depend on the wrong combination of packages.

Also, personally, I want people to call their packages “StringExtensions”. Currently the iOS development world is filled with silly names for packages, and this partly happens because the good names are already taken. People would instead say “Daniel Dunbar’s String Extensions” and for me, that is what the package should be called.

For packages like "libjpeg", "LLVM", "OpenGL", "ncurses", "zlib", it seems like having one global namespace is OK, and even useful. As a Python user, for example, I have never been bother that the Python package index is a global namespace.

Yes, this is separate (for me). And handled by module map packages.


(Daniel Dunbar) #14

I'm not sure this completely addresses my point... my argument was that while I understand the potential for collision when the major example is something related to "String", it still isn't clear to me that it is common enough to merit such a major feature. My point with examples like LLVM/libjpeg wasn't related to their style of package, but their uniqueness (which I see as a feature).

Is the argument that this problem is more severe because we have no index?

I think it would be good to see if we can get more data, too (e.g., more examples of collisions, or more evidence from other language communities).

- Daniel

···

On Feb 26, 2016, at 2:27 PM, Max Howell <max.howell@apple.com> wrote:

Can you explain a little more about your motivation for this?

I understand that "SwiftString", as a package, may be something which is likely to conflict. It isn't however clear to me that most packages fall into that category, or that it is even desirable to support features that encourage it.

I don’t mean to intercept Erica here, but I wanted to chime-in.

For me, my motivation is we don’t have a single index, so it is quite likely that module names will collide at some point.

We need some solution for this. Originally I was thinking, well lets allow overrides for module-names, which is still an option, but it is not as simple as I originally hoped since any packages that depend on that module in a deep tree will require either:

1) Swift-the-language support for the rename.
2) Or a preprocessor step in the Package Manager that renames module imports in affected packages.

Namespaces are more elegant, especially if by default you don’t have to care. Packages would only have to care if they import two modules with the same name, and this would be discovered by the package author, not by the end-user who just happened to depend on the wrong combination of packages.

Also, personally, I want people to call their packages “StringExtensions”. Currently the iOS development world is filled with silly names for packages, and this partly happens because the good names are already taken. People would instead say “Daniel Dunbar’s String Extensions” and for me, that is what the package should be called.

For packages like "libjpeg", "LLVM", "OpenGL", "ncurses", "zlib", it seems like having one global namespace is OK, and even useful. As a Python user, for example, I have never been bother that the Python package index is a global namespace.

Yes, this is separate (for me). And handled by module map packages.


(Joe Groff) #15

Yeah, that seems reasonable to me.

-Joe

···

On Feb 26, 2016, at 10:57 AM, Erica Sadun <erica@ericasadun.com> wrote:

On Feb 26, 2016, at 11:40 AM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

On Feb 26, 2016, at 10:30 AM, Max Howell <max.howell@apple.com <mailto:max.howell@apple.com>> wrote:

I first brought this topic up on swift-dev, and was pointed to swift-build-dev.

Having spent considerable time messing up my Swift packages by giving them ridiculously obvious names like SwiftString and SwiftCollections, I realized that namespacing would be a solution for disambiguating conflicts. import SwiftString is insufficient when several packages are named SwiftString.

When you have two identically named packages, the module imports need to distinguish both the sources as well as references defined per package. Although SwiftPM finds packages using git URLs and module names, I do not believe that origin is addressable or usable. Plus, throughout the lifetime of a package, that origin could potentially move from, for example, GitHub to Bitbucket.

I suggest using some kind of origin key for differentiation. The simplest solutions for these include reverse domain names (basically a company/source identifier), git URLs (the current location of the repo), Github/Bitbucket user names (which are similar to a company/source identifier but more subject to updates over time).

Of these, I’d recommend reverse domain for the following reasons:

They are relatively short
They are already well established for Apple app distribution
They do not rely on a web address that may change should the repo move
They are less likely to conflict with user names across repo hosts
I’d imagine a package declaration that looks something like this:

import PackageDescription

let package = Package(
    name: "SwiftString"
    origin: "org.sadun"
)
In the case of name conflicts instead of importing SwiftString, you’d prefix an origin:

import org.sadun.SwiftString
import com.foobar.SwiftString
Ideally, you could further alias these to shorten symbol disambiguation:

import org.sadun.SwiftString as SadunStrings
import com.foobar.SwiftString as FoobarStrings

// Unique to only one package, no name conflict
uniqueMethod("Hello World")

// name collision disambiguation
SadunStrings.sharedMethod("Hello World")
I'm interested in hearing any feedback and thoughts about whether this is possible and what I could do to help further this idea.

I think you have the right approach for sure. We need to talk with Swift-core as this will require work in that arena and they will need to chime in.

Certainly I would like to encourage namespacing with GitHub usernames because:

1) The majority of iOS open source happens there nowadays
2) People think of eg. mxcl’s PromiseKit, and thus both `import mxcl.PromiseKit` is very clear and communicates that these projects have origins/owners/maintainers.

However certainly I wouldn’t advocate for a GitHub only namespacing system, I just like that it have some extra sugar. SwiftPM was deliberately designed to be distributed.

I’ve cc’d Joe Groff since he probably can say something, then I can have some meetings, or we can try to do it all on the lists and then get this proposal written up.

Usernames strike me as too short to serve as a universal discriminator by themselves, and as you noted, tie the system to a specific service. Reverse-domain is certainly more precedented. I'm jumping into this conversation in the middle, so pardon me if this has already been discussed, but could the package manifest take responsibility for mapping global package identifiers to their source-level module names? That would let you say:

let dependencies = [
  "SadunString": "org.sadun.SwiftString",
  "FoobarStrings": "com.foobar.SwiftString"
]

and would give users some leeway to change their module references, should their dependencies end up forked or vendored.

Original post here: http://ericasadun.com/2016/02/08/naming-your-swift-packages/ and you really haven't missed much.

If you want to do it from the consumer end, then it becomes a lot simpler, without adding any specific origin information or adapting the package declaration. This is what it looks like now:
import PackageDescription
let package = Package (
    name: "myutility",
    dependencies: [
  .Package(url: "https://github.com/erica/SwiftString.git",
                 majorVersion: 1),
  .Package(url: "https://github.com/bob/SwiftString.git",
                 majorVersion: 1),
    ]
)
I'd imagine that you'd want to change it to look like this:
import PackageDescription
let package = Package (
    name: "myutility",
    dependencies: [
  .Package(url: "https://github.com/erica/SwiftString.git",
                 majorVersion: 1, localName: "SadunString"),
  .Package(url: "https://github.com/bob/SwiftString.git",
                 majorVersion: 1, localName: "BobString"),
    ]
)
If you leave off localName (or whatever it is called), it imports as the name declared in Package.name.


(Max Howell) #16

I think names like "Daniel Dunbar's String Extensions" is great when talking in English about a specific extension but I think the actual name should be as simple and elegant as possible without overlapping with built-in keywords.

Yes, indeed, I meant as you think: when talking out loud about things we refer to the package as “Daniel Dunbar’s String Extension”, but in the code we would want:

    import StringExtensions

or in the case of conflict:

    import ddunbar.StringExtensions

import org.sadun.StringUtilities // I can live with this but I'd rather import with a custom name established in dependencies

Another reason I think to avoid being able to customize the import name is for consistency in the packaging community. We should be trying to establish recognizable names.

···

On Feb 26, 2016, at 3:17 PM, Erica Sadun <erica@ericasadun.com> wrote:


(Max Howell) #17

I'm not sure this completely addresses my point... my argument was that while I understand the potential for collision when the major example is something related to "String", it still isn't clear to me that it is common enough to merit such a major feature. My point with examples like LLVM/libjpeg wasn't related to their style of package, but their uniqueness (which I see as a feature).

It’s not common, but it must be solved. I’m happy for us not to namespace if there is another solution that is just as good.

Is the argument that this problem is more severe because we have no index?

Indeed, it’s more severe because there is no single index.

I think it would be good to see if we can get more data, too (e.g., more examples of collisions, or more evidence from other language communities).

We can try to get more data, but I’m not sure it’s necessary since even if the data says it happens only 1% of the time we cannot just leave users out in the cold in such situations.

There are several solutions, but namespacing seems most in the spirit of a decentralized packaging ecosystem that has emerged due to GitHub’s rise to prominence and its username/repo design.

However I’d be happy with any solution that works and is easy for the user to get on with things in the event go Module name collision.

Max


(Erica Sadun) #18

I'll try writing up a proposal. Does everything work the same for swift-build-dev as -evolution?

-- E

···

On Feb 26, 2016, at 5:04 PM, Max Howell <max.howell@apple.com> wrote:

On Feb 26, 2016, at 3:17 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:

I think names like "Daniel Dunbar's String Extensions" is great when talking in English about a specific extension but I think the actual name should be as simple and elegant as possible without overlapping with built-in keywords.

Yes, indeed, I meant as you think: when talking out loud about things we refer to the package as “Daniel Dunbar’s String Extension”, but in the code we would want:

    import StringExtensions

or in the case of conflict:

    import ddunbar.StringExtensions

import org.sadun.StringUtilities // I can live with this but I'd rather import with a custom name established in dependencies

Another reason I think to avoid being able to customize the import name is for consistency in the packaging community. We should be trying to establish recognizable names.


(Daniel Dunbar) #19

Yup!

- Daniel

···

On Feb 29, 2016, at 8:53 AM, Erica Sadun <erica@ericasadun.com> wrote:

I'll try writing up a proposal. Does everything work the same for swift-build-dev as -evolution?

-- E

On Feb 26, 2016, at 5:04 PM, Max Howell <max.howell@apple.com <mailto:max.howell@apple.com>> wrote:

On Feb 26, 2016, at 3:17 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:

I think names like "Daniel Dunbar's String Extensions" is great when talking in English about a specific extension but I think the actual name should be as simple and elegant as possible without overlapping with built-in keywords.

Yes, indeed, I meant as you think: when talking out loud about things we refer to the package as “Daniel Dunbar’s String Extension”, but in the code we would want:

    import StringExtensions

or in the case of conflict:

    import ddunbar.StringExtensions

import org.sadun.StringUtilities // I can live with this but I'd rather import with a custom name established in dependencies

Another reason I think to avoid being able to customize the import name is for consistency in the packaging community. We should be trying to establish recognizable names.


(Max Howell) #20

So here is an example collision:

— Foo
     >——Bar
               >——Foo

Where both Foo modules are different packages.

I tested this situation with the PM already (each swift-module had its own build directory), and it failed to link, I cannot recall the exact reason. Now perhaps there is a way around that (perhaps dylibs and swiftc -module-link-name), if there is then we can avoid this whole situation provided that no single package wants to use two modules with the same name.

So this is not possible:

— Bar
     >——Foo (github.com/foo/Foo)
     >——Foo (github.com/baz/Foo)

But this is:

— Foo (github.com/bar/Foo)
     >——Bar
       >——Foo (github.com/baz/Foo)

It would still be nice to use two packages with the same name in the same package, but that is hopefully much less likely to happen. However with large dependency graphs it becomes increasingly likely that the example situation will happen.

···

On Feb 29, 2016, at 9:51 AM, Max Howell <max.howell@apple.com> wrote:

I'm not sure this completely addresses my point... my argument was that while I understand the potential for collision when the major example is something related to "String", it still isn't clear to me that it is common enough to merit such a major feature. My point with examples like LLVM/libjpeg wasn't related to their style of package, but their uniqueness (which I see as a feature).

It’s not common, but it must be solved. I’m happy for us not to namespace if there is another solution that is just as good.

Is the argument that this problem is more severe because we have no index?

Indeed, it’s more severe because there is no single index.

I think it would be good to see if we can get more data, too (e.g., more examples of collisions, or more evidence from other language communities).

We can try to get more data, but I’m not sure it’s necessary since even if the data says it happens only 1% of the time we cannot just leave users out in the cold in such situations.

There are several solutions, but namespacing seems most in the spirit of a decentralized packaging ecosystem that has emerged due to GitHub’s rise to prominence and its username/repo design.

However I’d be happy with any solution that works and is easy for the user to get on with things in the event go Module name collision.

Max