Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Swift registry support #1043

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions gazelle/internal/spdump/dependency.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ import (
type Dependency struct {
SourceControl *SourceControl `json:"sourceControl"`
FileSystem *FileSystem `json:"fileSystem"`
Registry *Registry `json:"registry"`
}

// Identity returns the value that identifies the external dependency in the manifest.
func (d *Dependency) Identity() string {
if d.SourceControl != nil {
return d.SourceControl.Identity
}
if d.Registry != nil {
return d.Registry.Identity
}
return ""
}

Expand Down Expand Up @@ -167,3 +171,23 @@ func (fs *FileSystem) UnmarshalJSON(b []byte) error {
fs.Path = rawFS.Path
return nil
}

type reg struct {
Identity string
}

// Registry represents the identity of an external dependency in a package registry.
type Registry struct {
watt marked this conversation as resolved.
Show resolved Hide resolved
Identity string
}

func (r *Registry) UnmarshalJSON(b []byte) error {
var raw []*reg
err := json.Unmarshal(b, &raw)
if err != nil {
return err
}
rawRegistry := raw[0]
r.Identity = rawRegistry.Identity
return nil
}
13 changes: 13 additions & 0 deletions gazelle/internal/spreso/pin.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const (
// A PinState is the interface that all underlying pin state representations must implement.
type PinState interface {
PinStateType() PinStateType
PinVersion() string
}

// BranchPinState
Expand All @@ -84,6 +85,10 @@ func (bps *BranchPinState) PinStateType() PinStateType {
return BranchPinStateType
}

func (bps *BranchPinState) PinVersion() string {
return ""
}

// Commit returns the source control commit value (e.g., hash).
func (bps *BranchPinState) Commit() string {
return bps.Revision
Expand All @@ -110,6 +115,10 @@ func (vps *VersionPinState) PinStateType() PinStateType {
return VersionPinStateType
}

func (vps *VersionPinState) PinVersion() string {
return vps.Version
}

// Commit returns the source control commit value (e.g., hash).
func (vps *VersionPinState) Commit() string {
return vps.Revision
Expand All @@ -132,6 +141,10 @@ func (rps *RevisionPinState) PinStateType() PinStateType {
return RevisionPinStateType
}

func (rps *RevisionPinState) PinVersion() string {
return ""
}

// Commit returns the source control commit value (e.g., hash).
func (rps *RevisionPinState) Commit() string {
return rps.Revision
Expand Down
6 changes: 3 additions & 3 deletions gazelle/internal/spreso/pin_store_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,12 @@ func NewPkgRefFromV2Pin(v2p *V2Pin) (*PackageReference, error) {
}

func NewPinStateFromV2PinState(ps *V2PinState) (PinState, error) {
if ps.Revision == "" {
return nil, fmt.Errorf("revision cannot be empty %+v", ps)
}
if ps.Version != "" {
return NewVersionPinState(ps.Version, ps.Revision), nil
}
if ps.Revision == "" {
return nil, fmt.Errorf("revision cannot be empty %+v", ps)
}
if ps.Branch != "" {
return NewBranchPinState(ps.Branch, ps.Revision), nil
}
Expand Down
8 changes: 8 additions & 0 deletions gazelle/internal/swift/code_dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,11 @@ func CodeDirForLocalPackage(pkgDir string, localPkgPath string) string {
// Return the local path
return filepath.Clean(path)
}

// CodeDirForRegistryPackage returns the path to the dependency's code. For registry dependencies,
// it is the path to the package downloaded from the registry.
func CodeDirForRegistryPackage(buildDir string, registryIdentity string, version string) string {
watt marked this conversation as resolved.
Show resolved Hide resolved
split := strings.Split(registryIdentity, ".")
scope, name := split[0], split[1]
return filepath.Join(buildDir, "registry", "downloads", scope, name, version)
}
15 changes: 14 additions & 1 deletion gazelle/internal/swift/repo_rule_from_bazel_repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ func RepoRuleFromBazelRepo(
) (*rule.Rule, error) {
var r *rule.Rule
var err error
if bzlRepo.Pin != nil {
if bzlRepo.Pin != nil && bzlRepo.Pin.PkgRef.Kind == spreso.RegistryPkgRefKind {
r = repoRuleForRegistryPackage(bzlRepo.Name, bzlRepo.Pin)
} else if bzlRepo.Pin != nil {
r, err = repoRuleFromPin(bzlRepo.Name, bzlRepo.Pin, patch)
if err != nil {
return nil, err
Expand Down Expand Up @@ -100,3 +102,14 @@ func repoRuleForLocalPackage(repoName string, path string) *rule.Rule {
r.SetAttr("path", path)
return r
}

func repoRuleForRegistryPackage(repoName string, pin *spreso.Pin) *rule.Rule {
identity := pin.PkgRef.Identity
version := pin.State.PinVersion()

r := rule.NewRule(RegistrySwiftPkgRuleKind, repoName)
r.SetAttr("id", identity)
r.SetAttr("version", version)

return r
}
7 changes: 4 additions & 3 deletions gazelle/internal/swift/rule_kinds.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ const (
TestRuleKind = "swift_test"

// Repository Rule
SwiftPkgRuleKind = "swift_package"
LocalSwiftPkgRuleKind = "local_swift_package"
HTTPArchiveRuleKind = "http_archive"
SwiftPkgRuleKind = "swift_package"
LocalSwiftPkgRuleKind = "local_swift_package"
RegistrySwiftPkgRuleKind = "swift_registry_package"
HTTPArchiveRuleKind = "http_archive"

AliasRuleKind = "alias"
)
Expand Down
19 changes: 19 additions & 0 deletions gazelle/internal/swiftpkg/dependency.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func (deps Dependencies) Identities() []string {
type Dependency struct {
SourceControl *SourceControl
FileSystem *FileSystem
Registry *Registry
}

// NewDependencyFromManifestInfo returns an external dependency based upon the manifest information.
Expand All @@ -34,9 +35,14 @@ func NewDependencyFromManifestInfo(dumpD *spdump.Dependency) (*Dependency, error
if dumpD.FileSystem != nil {
fSys = NewFileSystemFromManifestInfo(dumpD.FileSystem)
}
var registry *Registry
if dumpD.Registry != nil {
registry = NewRegistryFromManifestInfo(dumpD.Registry)
}
return &Dependency{
SourceControl: srcCtrl,
FileSystem: fSys,
Registry: registry,
}, nil
}

Expand All @@ -48,6 +54,9 @@ func (d *Dependency) Identity() string {
if d.FileSystem != nil {
return d.FileSystem.Identity
}
if d.Registry != nil {
return d.Registry.Identity
}
log.Fatalf("Identity could not be determined.")
return ""
}
Expand Down Expand Up @@ -147,3 +156,13 @@ func NewFileSystemFromManifestInfo(fs *spdump.FileSystem) *FileSystem {
Path: fs.Path,
}
}

type Registry struct {
Identity string
}

func NewRegistryFromManifestInfo(r *spdump.Registry) *Registry {
return &Registry{
Identity: r.Identity,
}
}
8 changes: 8 additions & 0 deletions gazelle/kinds.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ var kinds = map[string]rule.KindInfo{
"dependencies_index": true,
},
},
swift.RegistrySwiftPkgRuleKind: rule.KindInfo{
MatchAttrs: []string{
"url",
},
MergeableAttrs: map[string]bool{
"dependencies_index": true,
},
},
}

func (*swiftLang) Kinds() map[string]rule.KindInfo {
Expand Down
1 change: 1 addition & 0 deletions gazelle/lang.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func (*swiftLang) ApparentLoads(moduleToApparentName func(string) string) []rule
Symbols: []string{
swift.SwiftPkgRuleKind,
swift.LocalSwiftPkgRuleKind,
swift.RegistrySwiftPkgRuleKind,
},
},
}
Expand Down
10 changes: 8 additions & 2 deletions gazelle/update_repos.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,13 @@ func importReposFromPackageManifest(args language.ImportReposArgs) language.Impo
// which will have a spreso.Pin, and some will be local which will not have a spreso.Pin.
bzlReposByIdentity := make(map[string]*swift.BazelRepo)
for identity, pin := range pinsByIdentity {
depDir := swift.CodeDirForRemotePackage(buildDir, pin.PkgRef.Remote())
depDir := ""
if pin.PkgRef.Kind == spreso.RegistryPkgRefKind {
version := pin.State.PinVersion()
depDir = swift.CodeDirForRegistryPackage(buildDir, pin.PkgRef.Identity, version)
} else {
depDir = swift.CodeDirForRemotePackage(buildDir, pin.PkgRef.Remote())
}
depPkgInfo, dpierr := swiftpkg.NewPackageInfo(sb, depDir, "")
if dpierr != nil {
result.Error = dpierr
Expand Down Expand Up @@ -199,7 +205,7 @@ func importReposFromPackageManifest(args language.ImportReposArgs) language.Impo
for _, r := range c.Repos {
kind := r.Kind()
switch kind {
case swift.SwiftPkgRuleKind, swift.LocalSwiftPkgRuleKind:
case swift.SwiftPkgRuleKind, swift.LocalSwiftPkgRuleKind, swift.RegistrySwiftPkgRuleKind:
if name := r.Name(); !repoUsage[name] {
result.Empty = append(result.Empty, rule.NewRule(kind, name))
}
Expand Down
2 changes: 2 additions & 0 deletions swiftpkg/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

load("//swiftpkg/internal:local_swift_package.bzl", _local_swift_package = "local_swift_package")
load("//swiftpkg/internal:swift_package.bzl", _swift_package = "swift_package")
load("//swiftpkg/internal:swift_registry_package.bzl", _swift_registry_package = "swift_registry_package")
load("//swiftpkg/internal:swift_update_packages.bzl", _swift_update_packages = "swift_update_packages")

# Repository rules
swift_package = _swift_package
local_swift_package = _local_swift_package
swift_registry_package = _swift_registry_package

# Gazelle macros
swift_update_packages = _swift_update_packages
34 changes: 34 additions & 0 deletions swiftpkg/internal/registry_configs.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Module for resolving registry URLs from scopes."""

def _read(repository_ctx):
registry_config_json = repository_ctx.read(
repository_ctx.attr.registry_config,
)
registry_config = _new_from_json(registry_config_json)
return registry_config

def _new_from_json(json_str):
"""Creates a registry config from a JSON string.

Args:
json_str: A JSON `string` value.

Returns:
A `dict` that contains a registry config.
"""
return json.decode(json_str)

def _get_url_for_scope(registry_config, scope):
registries = registry_config.get("registries", {})

registry = registries.get(scope) or registries.get("[default]")

if not registry:
fail("No registry configured for scope '%s'." % scope)

return registry["url"]

registry_configs = struct(
read = _read,
get_url_for_scope = _get_url_for_scope,
)
6 changes: 6 additions & 0 deletions swiftpkg/internal/repository_files.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,11 @@ def _file_type(repository_ctx, path):
))
return exec_result.stdout.removesuffix("\n")

def _remove_bazel_files(repository_ctx, directory):
files = ["BUILD.bazel", "BUILD", "WORKSPACE", "WORKSPACE.bazel"]
for file in files:
_find_and_delete_files(repository_ctx, directory, file)

repository_files = struct(
copy_directory = _copy_directory,
exclude_paths = _exclude_paths,
Expand All @@ -243,6 +248,7 @@ repository_files = struct(
list_directories_under = _list_directories_under,
list_files_under = _list_files_under,
path_exists = _path_exists,
remove_bazel_files = _remove_bazel_files,
# Exposed for testing purposes only.
process_find_results = _process_find_results,
)
7 changes: 1 addition & 6 deletions swiftpkg/internal/swift_package.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,6 @@ def _update_git_attrs(orig, keys, override):
result.pop("branch", None)
return result

def _remove_bazel_files(repository_ctx, directory):
files = ["BUILD.bazel", "BUILD", "WORKSPACE", "WORKSPACE.bazel"]
for file in files:
repository_files.find_and_delete_files(repository_ctx, directory, file)

def _swift_package_impl(repository_ctx):
directory = str(repository_ctx.path("."))
env = repo_rules.get_exec_env(repository_ctx)
Expand All @@ -56,7 +51,7 @@ def _swift_package_impl(repository_ctx):
patch(repository_ctx)

# Remove any Bazel build files.
_remove_bazel_files(repository_ctx, directory)
repository_files.remove_bazel_files(repository_ctx, directory)

# Generate the WORKSPACE file
repo_rules.write_workspace_file(repository_ctx, directory)
Expand Down
Loading
Loading