Revisiting package conflicts


(Erica Sadun) #1

I'm trying to clean up a few things while my kids are on Spring Break and decided to rewrite my package
conflict proposal, which follows.

This updated version does not require any language change (although one could be adopted later), does not
require any package change, and only affects the target directories and module names.

I'd appreciate any feedback you could give.

Thanks, -- Erica

Disambiguating SwiftPM Naming Conflicts

Proposal: TBD
Author(s): Erica Sadun <http://github.com/erica>
Status: TBD
Review manager: TBD
<https://gist.github.com/erica/c6553a5f6f35e7462074#introduction>Introduction

This proposal creates a way to resolve SwiftPM module conflicts. It introduces namespacing to handle the rare case of name overlaps without requiring a central package registry.

This proposal was discussed on the Swift-Dev and Swift-Build-Dev lists in the "Right List? <http://article.gmane.org/gmane.comp.lang.swift.devel/1149>" thread.

<https://gist.github.com/erica/c6553a5f6f35e7462074#motivation>Motivation

Swift offers a built in mechanism for distinguishing symbol conflicts. When working with NSView, using Swift.printoutputs text to the console or stream. NSView's print creates a print job. Swift does not yet offer a solution for conflicting module names.

Like many other Swift developers, I have spent considerable time building utility packages. Mine use obvious names like SwiftString and SwiftCollections because simple clear naming is a hallmark of Swift design. At the same time, this style introduces the possibility of package name conflicts.

import SwiftString // mine
import SwiftString // someone else's. oops.
Two SwiftString packages cannot be used simultaneously without some form of namespace resolution. Moving back to Cocoa-style namespacing, for example ESSwiftString, feels ugly and antithetical to Swift. Swift should encourage recognizable, easy-to-understand module names. This proposal addresses this rare but possible conflict.

Under the current system, same-named modules:

import PackageDescription
let package = Package (
    name: "myutility",
        dependencies: [
        .Package(url: "https://github.com/erica/SwiftString.git",
                 majorVersion: 1),
        .Package(url: "https://github.com/nudas/SwiftString.git",
                 majorVersion: 1),
        ]

)
produce the following error:

% swift build
Cloning Packages/SwiftString
Using version 1.0.5 of package SwiftString
Cloning Packages/SwiftString
/usr/bin/git clone --recursive --depth 10 https://github.com/nudas/SwiftString.git /home/erica/Work/test/Packages/SwiftString
fatal: destination path '/home/erica/Work/test/Packages/SwiftString' already exists and is not an empty directory.

swift-build: Failed to clone https://github.com/nudas/SwiftString.git to /home/erica/Work/test/Packages/SwiftString
Makefile:3: recipe for target 'all' failed
make: *** [all] Error 1
<https://gist.github.com/erica/c6553a5f6f35e7462074#detail-design>Detail Design

Under this proposal, the Swift Package manager uses reverse domain naming to differentiate otherwise identically-named items. The two conflicting packages in the following example:

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),
    ]
)
unpack to Packages/com.github.erica.SwiftString and Packages/com.github.bob.SwiftString rather than Packages/SwiftString.

These can then be imported using the full RDN notation:

import com.github.erica.SwiftString
import com.github.bob.SwiftString
Reverse domain names

are rarely used outside the import statement and only to distinguish overlapping implementations
are relatively short
are already well established for Apple app distribution
are tied to the hosting repo
<https://gist.github.com/erica/c6553a5f6f35e7462074#future-directions>Future Directions

However concise, using reverse domain names bring verbiage to name conflicts. Upon adopting this proposal, I intend following through with language specific proposals that allow either import as or right-to-left namespacing.

A Swift import as statement would allow a developer to rename a module on import:

import com.github.erica.SwiftString as EricaString
A right-to-left alternative would require only as much of the reverse domain name prefix as needed to distinguish one implementation from another, for example:

erica.SwiftString.print(x)
bob.SwiftString.print(x)
although presumably the fully specified RDN prefix could be used as well:

com.github.erica.SwiftString.print(x)
<https://gist.github.com/erica/c6553a5f6f35e7462074#acknowledgements>Acknowledgements

Thanks to Joe Groff <https://github.com/jckarter>, Ankit Aggarwal <https://github.com/aciidb0mb3r>, Max Howell, Daniel Dunbar, Kostiantyn Koval


(Ankit Agarwal) #2

I think if swiftpm renames `SwiftString` to `com.github.erica.SwiftString`,
any other dependency having either `SwiftString` as dependency will not be
able to use `import SwiftString` and thus fail to build.

···

On Thu, Mar 31, 2016 at 11:54 PM, Erica Sadun <erica@ericasadun.com> wrote:

I'm trying to clean up a few things while my kids are on Spring Break and
decided to rewrite my package
conflict proposal, which follows.

This updated version does not require any language change (although one
could be adopted later), does not
require any package change, and only affects the target directories and
module names.

I'd appreciate any feedback you could give.

Thanks, -- Erica

Disambiguating SwiftPM Naming Conflicts

   - Proposal: TBD
   - Author(s): Erica Sadun <http://github.com/erica>
   - Status: TBD
   - Review manager: TBD

<https://gist.github.com/erica/c6553a5f6f35e7462074#introduction>
Introduction

This proposal creates a way to resolve SwiftPM module conflicts. It
introduces namespacing to handle the rare case of name overlaps without
requiring a central package registry.

This proposal was discussed on the Swift-Dev and Swift-Build-Dev lists in
the "Right List?
<http://article.gmane.org/gmane.comp.lang.swift.devel/1149>" thread.
<https://gist.github.com/erica/c6553a5f6f35e7462074#motivation>Motivation

Swift offers a built in mechanism for distinguishing symbol conflicts.
When working with NSView, using Swift.printoutputs text to the console or
stream. NSView's print creates a print job. Swift does not yet offer a
solution for conflicting module names.

Like many other Swift developers, I have spent considerable time building
utility packages. Mine use obvious names like SwiftString and
SwiftCollections because simple clear naming is a hallmark of Swift
design. At the same time, this style introduces the possibility of package
name conflicts.

import SwiftString // mineimport SwiftString // someone else's. oops.

Two SwiftString packages cannot be used simultaneously without some form
of namespace resolution. Moving back to Cocoa-style namespacing, for
example ESSwiftString, feels ugly and antithetical to Swift. Swift should
encourage recognizable, easy-to-understand module names. This proposal
addresses this rare but possible conflict.

Under the current system, same-named modules:

import PackageDescription
let package = Package (
    name: "myutility",
        dependencies: [
        .Package(url: "https://github.com/erica/SwiftString.git",
                 majorVersion: 1),
        .Package(url: "https://github.com/nudas/SwiftString.git",
                 majorVersion: 1),
        ]

)

produce the following error:

% swift build
Cloning Packages/SwiftString
Using version 1.0.5 of package SwiftString
Cloning Packages/SwiftString
/usr/bin/git clone --recursive --depth 10 https://github.com/nudas/SwiftString.git /home/erica/Work/test/Packages/SwiftString
fatal: destination path '/home/erica/Work/test/Packages/SwiftString' already exists and is not an empty directory.

swift-build: Failed to clone https://github.com/nudas/SwiftString.git to /home/erica/Work/test/Packages/SwiftString
Makefile:3: recipe for target 'all' failed
make: *** [all] Error 1

<https://gist.github.com/erica/c6553a5f6f35e7462074#detail-design>Detail
Design

Under this proposal, the Swift Package manager uses reverse domain naming
to differentiate otherwise identically-named items. The two conflicting
packages in the following example:

import PackageDescriptionlet 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),
    ]
)

unpack to Packages/com.github.erica.SwiftString and
Packages/com.github.bob.SwiftString rather than Packages/SwiftString.

These can then be imported using the full RDN notation:

import com.github.erica.SwiftString
import com.github.bob.SwiftString

Reverse domain names

   - are rarely used outside the import statement and only to distinguish
   overlapping implementations
   - are relatively short
   - are already well established for Apple app distribution
   - are tied to the hosting repo

<https://gist.github.com/erica/c6553a5f6f35e7462074#future-directions>Future
Directions

However concise, using reverse domain names bring verbiage to name
conflicts. Upon adopting this proposal, I intend following through with
language specific proposals that allow either import as or right-to-left
namespacing.

A Swift import as statement would allow a developer to rename a module on
import:

import com.github.erica.SwiftString as EricaString

A right-to-left alternative would require only as much of the reverse
domain name prefix as needed to distinguish one implementation from
another, for example:

erica.SwiftString.print(x)
bob.SwiftString.print(x)

although presumably the fully specified RDN prefix could be used as well:

com.github.erica.SwiftString.print(x)

<https://gist.github.com/erica/c6553a5f6f35e7462074#acknowledgements>
Acknowledgements
Thanks to Joe Groff <https://github.com/jckarter>, Ankit Aggarwal
<https://github.com/aciidb0mb3r>, Max Howell, Daniel Dunbar, Kostiantyn
Koval

--
Ankit


(Daniel Dunbar) #3

I think my high level opinion on this problem is that it is still a questionable thing to support in this particular form.

I agree that using clear names, like SwiftString, is useful. However, I also think it would be very unfortunate if a product ended up using a SwiftString module from multiple authors within a single build graph. That would be confusing to work on, and especially doing it without involvement from Swift the language would be problematic (e.g., there might be mangling collisions, how would the user understand which types they were seeing in places outside of a specific module with an explicit import).

I think having more namespacing options at the language level is the right place to push on this, after which SwiftPM can adopt them (if indeed any work is required).

For example, one situation where I think this is reasonable to support is when a large package has a complicated internal module structure, most of which clients cannot see. Such a package might want to have a "Util" module, as might many other such packages, and they shouldn't collide. However, for this case to work the package needs to be written in such a way that it is clear which imports have visibility into which namespaces, it isn't just a renaming operation at the SwiftPM level.

- Daniel

···

On Mar 31, 2016, at 11:24 AM, Erica Sadun <erica@ericasadun.com> wrote:

I'm trying to clean up a few things while my kids are on Spring Break and decided to rewrite my package
conflict proposal, which follows.

This updated version does not require any language change (although one could be adopted later), does not
require any package change, and only affects the target directories and module names.

I'd appreciate any feedback you could give.

Thanks, -- Erica

Disambiguating SwiftPM Naming Conflicts

Proposal: TBD
Author(s): Erica Sadun <http://github.com/erica>
Status: TBD
Review manager: TBD
<https://gist.github.com/erica/c6553a5f6f35e7462074#introduction>Introduction

This proposal creates a way to resolve SwiftPM module conflicts. It introduces namespacing to handle the rare case of name overlaps without requiring a central package registry.

This proposal was discussed on the Swift-Dev and Swift-Build-Dev lists in the "Right List? <http://article.gmane.org/gmane.comp.lang.swift.devel/1149>" thread.

<https://gist.github.com/erica/c6553a5f6f35e7462074#motivation>Motivation

Swift offers a built in mechanism for distinguishing symbol conflicts. When working with NSView, using Swift.printoutputs text to the console or stream. NSView's print creates a print job. Swift does not yet offer a solution for conflicting module names.

Like many other Swift developers, I have spent considerable time building utility packages. Mine use obvious names like SwiftString and SwiftCollections because simple clear naming is a hallmark of Swift design. At the same time, this style introduces the possibility of package name conflicts.

import SwiftString // mine
import SwiftString // someone else's. oops.
Two SwiftString packages cannot be used simultaneously without some form of namespace resolution. Moving back to Cocoa-style namespacing, for example ESSwiftString, feels ugly and antithetical to Swift. Swift should encourage recognizable, easy-to-understand module names. This proposal addresses this rare but possible conflict.

Under the current system, same-named modules:

import PackageDescription
let package = Package (
    name: "myutility",
        dependencies: [
        .Package(url: "https://github.com/erica/SwiftString.git",
                 majorVersion: 1),
        .Package(url: "https://github.com/nudas/SwiftString.git",
                 majorVersion: 1),
        ]

)
produce the following error:

% swift build
Cloning Packages/SwiftString
Using version 1.0.5 of package SwiftString
Cloning Packages/SwiftString
/usr/bin/git clone --recursive --depth 10 https://github.com/nudas/SwiftString.git /home/erica/Work/test/Packages/SwiftString
fatal: destination path '/home/erica/Work/test/Packages/SwiftString' already exists and is not an empty directory.

swift-build: Failed to clone https://github.com/nudas/SwiftString.git to /home/erica/Work/test/Packages/SwiftString
Makefile:3: recipe for target 'all' failed
make: *** [all] Error 1
<https://gist.github.com/erica/c6553a5f6f35e7462074#detail-design>Detail Design

Under this proposal, the Swift Package manager uses reverse domain naming to differentiate otherwise identically-named items. The two conflicting packages in the following example:

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),
    ]
)
unpack to Packages/com.github.erica.SwiftString and Packages/com.github.bob.SwiftString rather than Packages/SwiftString.

These can then be imported using the full RDN notation:

import com.github.erica.SwiftString
import com.github.bob.SwiftString
Reverse domain names

are rarely used outside the import statement and only to distinguish overlapping implementations
are relatively short
are already well established for Apple app distribution
are tied to the hosting repo
<https://gist.github.com/erica/c6553a5f6f35e7462074#future-directions>Future Directions

However concise, using reverse domain names bring verbiage to name conflicts. Upon adopting this proposal, I intend following through with language specific proposals that allow either import as or right-to-left namespacing.

A Swift import as statement would allow a developer to rename a module on import:

import com.github.erica.SwiftString as EricaString
A right-to-left alternative would require only as much of the reverse domain name prefix as needed to distinguish one implementation from another, for example:

erica.SwiftString.print(x)
bob.SwiftString.print(x)
although presumably the fully specified RDN prefix could be used as well:

com.github.erica.SwiftString.print(x)
<https://gist.github.com/erica/c6553a5f6f35e7462074#acknowledgements>Acknowledgements

Thanks to Joe Groff <https://github.com/jckarter>, Ankit Aggarwal <https://github.com/aciidb0mb3r>, Max Howell, Daniel Dunbar, Kostiantyn Koval


(Erica Sadun) #4

*headbang* *headbang* *headbang*

Possible situations:

* One package knows there's name conflicts, uses full dependency reverse namespacing
* Dependent package does not know there's name conflicts, but it has a dependency listed, so it uses only the nearest/most visible declaration.

Is there a way to resolve using some sort of rule system so that this somehow works? Can I assume that each module is compiled from the bottom to the top of the dependency graph so that the only conflicts ever seen would be higher in the graph where they know a priori that there's a more complicated import?

-- E

···

On Mar 31, 2016, at 12:37 PM, Ankit Agarwal <ankit@ankit.im> wrote:

I think if swiftpm renames `SwiftString` to `com.github.erica.SwiftString`, any other dependency having either `SwiftString` as dependency will not be able to use `import SwiftString` and thus fail to build.

On Thu, Mar 31, 2016 at 11:54 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:
I'm trying to clean up a few things while my kids are on Spring Break and decided to rewrite my package
conflict proposal, which follows.

This updated version does not require any language change (although one could be adopted later), does not
require any package change, and only affects the target directories and module names.

I'd appreciate any feedback you could give.

Thanks, -- Erica


(Max Howell) #5

I’m sorry I haven’t been as active in this issue.

For me, this is one of the really important issues and I want to make sure we do it right, so I’m letting my mind spin on it regularly.

Namespacing is more than just avoiding conflicts, it becomes part of a package’s identity, so it has social and community consequences.

···

On Mar 31, 2016, at 3:20 PM, Erica Sadun <erica@ericasadun.com> wrote:

*headbang* *headbang* *headbang*

Possible situations:

* One package knows there's name conflicts, uses full dependency reverse namespacing
* Dependent package does not know there's name conflicts, but it has a dependency listed, so it uses only the nearest/most visible declaration.

Is there a way to resolve using some sort of rule system so that this somehow works? Can I assume that each module is compiled from the bottom to the top of the dependency graph so that the only conflicts ever seen would be higher in the graph where they know a priori that there's a more complicated import?

-- E

On Mar 31, 2016, at 12:37 PM, Ankit Agarwal <ankit@ankit.im <mailto:ankit@ankit.im>> wrote:

I think if swiftpm renames `SwiftString` to `com.github.erica.SwiftString`, any other dependency having either `SwiftString` as dependency will not be able to use `import SwiftString` and thus fail to build.

On Thu, Mar 31, 2016 at 11:54 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:
I'm trying to clean up a few things while my kids are on Spring Break and decided to rewrite my package
conflict proposal, which follows.

This updated version does not require any language change (although one could be adopted later), does not
require any package change, and only affects the target directories and module names.

I'd appreciate any feedback you could give.

Thanks, -- Erica


(Max Howell) #6

Collision in the wild: https://bugs.swift.org/browse/SR-1168

···

On Apr 3, 2016, at 11:43 PM, Daniel Dunbar <daniel_dunbar@apple.com> wrote:

I think my high level opinion on this problem is that it is still a questionable thing to support in this particular form.

I agree that using clear names, like SwiftString, is useful. However, I also think it would be very unfortunate if a product ended up using a SwiftString module from multiple authors within a single build graph. That would be confusing to work on, and especially doing it without involvement from Swift the language would be problematic (e.g., there might be mangling collisions, how would the user understand which types they were seeing in places outside of a specific module with an explicit import).

I think having more namespacing options at the language level is the right place to push on this, after which SwiftPM can adopt them (if indeed any work is required).

For example, one situation where I think this is reasonable to support is when a large package has a complicated internal module structure, most of which clients cannot see. Such a package might want to have a "Util" module, as might many other such packages, and they shouldn't collide. However, for this case to work the package needs to be written in such a way that it is clear which imports have visibility into which namespaces, it isn't just a renaming operation at the SwiftPM level.

- Daniel

On Mar 31, 2016, at 11:24 AM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:

I'm trying to clean up a few things while my kids are on Spring Break and decided to rewrite my package
conflict proposal, which follows.

This updated version does not require any language change (although one could be adopted later), does not
require any package change, and only affects the target directories and module names.

I'd appreciate any feedback you could give.

Thanks, -- Erica

Disambiguating SwiftPM Naming Conflicts
Proposal: TBD
Author(s): Erica Sadun <http://github.com/erica>
Status: TBD
Review manager: TBD
<https://gist.github.com/erica/c6553a5f6f35e7462074#introduction>Introduction

This proposal creates a way to resolve SwiftPM module conflicts. It introduces namespacing to handle the rare case of name overlaps without requiring a central package registry.

This proposal was discussed on the Swift-Dev and Swift-Build-Dev lists in the "Right List? <http://article.gmane.org/gmane.comp.lang.swift.devel/1149>" thread.

<https://gist.github.com/erica/c6553a5f6f35e7462074#motivation>Motivation

Swift offers a built in mechanism for distinguishing symbol conflicts. When working with NSView, using Swift.printoutputs text to the console or stream. NSView's print creates a print job. Swift does not yet offer a solution for conflicting module names.

Like many other Swift developers, I have spent considerable time building utility packages. Mine use obvious names like SwiftString and SwiftCollections because simple clear naming is a hallmark of Swift design. At the same time, this style introduces the possibility of package name conflicts.

import SwiftString // mine
import SwiftString // someone else's. oops.
Two SwiftString packages cannot be used simultaneously without some form of namespace resolution. Moving back to Cocoa-style namespacing, for example ESSwiftString, feels ugly and antithetical to Swift. Swift should encourage recognizable, easy-to-understand module names. This proposal addresses this rare but possible conflict.

Under the current system, same-named modules:

import PackageDescription
let package = Package (
    name: "myutility",
        dependencies: [
        .Package(url: "https://github.com/erica/SwiftString.git",
                 majorVersion: 1),
        .Package(url: "https://github.com/nudas/SwiftString.git",
                 majorVersion: 1),
        ]

)
produce the following error:

% swift build
Cloning Packages/SwiftString
Using version 1.0.5 of package SwiftString
Cloning Packages/SwiftString
/usr/bin/git clone --recursive --depth 10 https://github.com/nudas/SwiftString.git /home/erica/Work/test/Packages/SwiftString
fatal: destination path '/home/erica/Work/test/Packages/SwiftString' already exists and is not an empty directory.

swift-build: Failed to clone https://github.com/nudas/SwiftString.git to /home/erica/Work/test/Packages/SwiftString
Makefile:3: recipe for target 'all' failed
make: *** [all] Error 1
<https://gist.github.com/erica/c6553a5f6f35e7462074#detail-design>Detail Design

Under this proposal, the Swift Package manager uses reverse domain naming to differentiate otherwise identically-named items. The two conflicting packages in the following example:

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),
    ]
)
unpack to Packages/com.github.erica.SwiftString and Packages/com.github.bob.SwiftString rather than Packages/SwiftString.

These can then be imported using the full RDN notation:

import com.github.erica.SwiftString
import com.github.bob.SwiftString
Reverse domain names

are rarely used outside the import statement and only to distinguish overlapping implementations
are relatively short
are already well established for Apple app distribution
are tied to the hosting repo
<https://gist.github.com/erica/c6553a5f6f35e7462074#future-directions>Future Directions

However concise, using reverse domain names bring verbiage to name conflicts. Upon adopting this proposal, I intend following through with language specific proposals that allow either import as or right-to-left namespacing.

A Swift import as statement would allow a developer to rename a module on import:

import com.github.erica.SwiftString as EricaString
A right-to-left alternative would require only as much of the reverse domain name prefix as needed to distinguish one implementation from another, for example:

erica.SwiftString.print(x)
bob.SwiftString.print(x)
although presumably the fully specified RDN prefix could be used as well:

com.github.erica.SwiftString.print(x)
<https://gist.github.com/erica/c6553a5f6f35e7462074#acknowledgements>Acknowledgements

Thanks to Joe Groff <https://github.com/jckarter>, Ankit Aggarwal <https://github.com/aciidb0mb3r>, Max Howell, Daniel Dunbar, Kostiantyn Koval