/
pkgcontext.go
148 lines (131 loc) · 4.88 KB
/
pkgcontext.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package pkgcontext
import (
"path/filepath"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/google/go-github/github"
"github.com/pkg/errors"
"github.com/Southclaws/sampctl/build"
"github.com/Southclaws/sampctl/pawnpackage"
"github.com/Southclaws/sampctl/print"
"github.com/Southclaws/sampctl/run"
"github.com/Southclaws/sampctl/versioning"
)
// PackageContext stores state for a package during its lifecycle.
type PackageContext struct {
Package pawnpackage.Package // the package this context wraps
GitHub *github.Client // GitHub client for downloading plugins
GitAuth transport.AuthMethod // Authentication method for git
Platform string // the platform this package targets
CacheDir string // the cache directory
AllDependencies []versioning.DependencyMeta // flattened list of dependencies
AllPlugins []versioning.DependencyMeta // flattened list of plugin dependencies
AllIncludePaths []string // any additional include paths specified by resources
ActualRuntime run.Runtime // actual runtime configuration to use for running the package
ActualBuild build.Config // actual build configuration to use for running the package
// Runtime specific fields
Runtime string // the runtime config to use, defaults to `default`
Container bool // whether or not to run the package in a container
AppVersion string // the version of sampctl
BuildName string // Build configuration to use
ForceBuild bool // Force a build before running
ForceEnsure bool // Force an ensure before building before running
NoCache bool // Don't use a cache, download all plugin dependencies
BuildFile string // File to increment build number
Relative bool // Show output as relative paths
}
// NewPackageContext attempts to parse a directory as a Package by looking for a
// `pawn.json` or `pawn.yaml` file and unmarshalling it - additional parameters
// are required to specify whether or not the package is a "parent package" and
// where the vendor directory is.
func NewPackageContext(
gh *github.Client,
auth transport.AuthMethod,
parent bool,
dir string,
platform string,
cacheDir string,
vendor string,
init bool,
) (pcx *PackageContext, err error) {
pcx = &PackageContext{
GitHub: gh,
GitAuth: auth,
Platform: platform,
CacheDir: cacheDir,
}
pcx.Package, err = pawnpackage.PackageFromDir(dir)
if err != nil {
err = errors.Wrap(err, "failed to read package definition")
return
}
pcx.Package.Parent = parent
pcx.Package.LocalPath = dir
if !init {
pcx.Package.Tag = getPackageTag(dir)
} else {
pcx.Package.Tag = ""
}
print.Verb(pcx.Package, "read package from directory", dir)
if vendor == "" {
pcx.Package.Vendor = filepath.Join(dir, "dependencies")
} else {
pcx.Package.Vendor = vendor
}
if err = pcx.Package.Validate(); err != nil {
err = errors.Wrap(err, "package validation failed during initial read")
return
}
// user and repo are not mandatory but are recommended, warn the user if this is their own
// package (parent == true) but ignore for dependencies (parent == false)
if !init {
if pcx.Package.User == "" {
if parent {
print.Warn(pcx.Package, "Package Definition File does specify a value for `user`.")
}
pcx.Package.User = "<none>"
}
if pcx.Package.Repo == "" {
if parent {
print.Warn(pcx.Package, "Package Definition File does specify a value for `repo`.")
}
pcx.Package.Repo = "<local>"
}
}
// if there is no runtime configuration, use the defaults
if pcx.Package.Runtime == nil {
pcx.Package.Runtime = new(run.Runtime)
}
run.ApplyRuntimeDefaults(pcx.Package.Runtime)
print.Verb(pcx.Package, "building dependency tree and ensuring cached copies")
err = pcx.EnsureDependenciesCached()
if err != nil {
err = errors.Wrap(err, "failed to ensure dependencies are cached")
return
}
print.Verb(pcx.Package, "flattened dependencies to", len(pcx.AllDependencies), "leaves")
return pcx, nil
}
func getPackageTag(dir string) (tag string) {
repo, err := git.PlainOpen(dir)
if err != nil {
// repo may be intentionally not a git repo, so only print verbosely
if errors.Is(err, git.ErrRepositoryNotExists) {
print.Verb("failed to open repo:", dir, "is not a git repo")
return
}
print.Erro("failed to open repo (", dir, "):", err)
return
} else {
vtag, errInner := versioning.GetRepoCurrentVersionedTag(repo)
if errInner != nil {
// error information only needs to be printed with --verbose
print.Verb("failed to get version information:", errInner)
// but we can let the user know that they should version their code!
print.Info("Package does not have any tags, consider versioning your code with: `sampctl package release`")
} else if vtag != nil {
tag = vtag.Name
}
}
return
}