44package downloadsources
55
66import (
7- "errors"
87 "fmt"
98 "log/slog"
109 "path/filepath"
1110
1211 "github.com/microsoft/azure-linux-dev-tools/internal/app/azldev"
12+ "github.com/microsoft/azure-linux-dev-tools/internal/app/azldev/core/components"
13+ "github.com/microsoft/azure-linux-dev-tools/internal/providers/sourceproviders"
1314 "github.com/microsoft/azure-linux-dev-tools/internal/providers/sourceproviders/fedorasource"
1415 "github.com/microsoft/azure-linux-dev-tools/internal/utils/downloader"
15- "github.com/microsoft/azure-linux-dev-tools/internal/utils/fileutils"
1616 "github.com/microsoft/azure-linux-dev-tools/internal/utils/retry"
1717 "github.com/spf13/cobra"
1818)
@@ -22,7 +22,7 @@ type DownloadSourcesOptions struct {
2222 Directory string
2323 OutputDir string
2424 LookasideBaseURIs []string
25- PackageName string
25+ ComponentName string
2626 LookasideDownloader fedorasource.FedoraSourceDownloader
2727}
2828
@@ -45,28 +45,29 @@ The command reads the 'sources' file, resolves the lookaside cache URI from
4545the distro configuration, and downloads each listed file into the directory.
4646Files that already exist in the directory are skipped.
4747
48- The package name is derived from the directory name and can be overridden
49- with --package-name. The directory must contain a 'sources' file.
48+ Either --component or --lookaside-uri must be provided:
5049
51- This command can run without project configuration by providing
52- --lookaside-uri explicitly.` ,
53- Example : ` # Download sources in the current directory (package name derived from dir name)
54- azldev advanced download-sources
50+ --component (-p) Uses the component's distro configuration to resolve
51+ the lookaside URI and package name.
52+ --lookaside-uri Provides the URI explicitly (no project config needed).
53+ Package name is derived from the directory name.` ,
54+ Example : ` # Download sources for a component (uses component's distro config)
55+ azldev advanced download-sources -p curl
5556
56- # Download sources from a specific directory
57- azldev advanced download-sources -d ./path/to/curl/
57+ # Download sources using explicit lookaside URI (no config needed)
58+ azldev advanced download-sources \
59+ --lookaside-uri 'https://example.com/$pkg/$filename/$hashtype/$hash/$filename'
5860
59- # Download sources to a different output directory
60- azldev advanced download-sources -o /tmp/output
61+ # Specify a different source directory
62+ azldev advanced download-sources -p curl -d ./path/to/sources/
6163
62- # Download sources using explicit lookaside URIs
63- azldev advanced download-sources \\
64- --lookaside-uri https://example.com/cache1 \\
65- --lookaside-uri https://example.com/cache2
64+ # Download to a different output directory
65+ azldev advanced download-sources -p curl -o /tmp/output
6666
67- # Download sources without project configuration
68- azldev advanced download-sources \\
69- --lookaside-uri https://example.com/cache -d ./curl` ,
67+ # Try multiple lookaside URIs in order
68+ azldev advanced download-sources \
69+ --lookaside-uri 'https://cache1.example.com/$pkg/$filename/$hashtype/$hash/$filename' \
70+ --lookaside-uri 'https://cache2.example.com/$pkg/$filename/$hashtype/$hash/$filename'` ,
7071 RunE : azldev .RunFuncWithoutRequiredConfig (func (env * azldev.Env ) (interface {}, error ) {
7172 if options .Directory == "" {
7273 options .Directory = "."
@@ -84,11 +85,15 @@ This command can run without project configuration by providing
8485 "output directory for downloaded files (defaults to source directory)" )
8586 _ = cmd .MarkFlagDirname ("output-dir" )
8687
88+ cmd .Flags ().StringVarP (& options .ComponentName , "component" , "p" , "" ,
89+ "component name to resolve distro and package name from" )
90+
8791 cmd .Flags ().StringArrayVar (& options .LookasideBaseURIs , "lookaside-uri" , nil ,
88- "explicit lookaside base URI(s) to use instead of the distro configuration (can be specified multiple times)" )
92+ "explicit lookaside base URI(s) to try in order, first success wins " +
93+ "(can be specified multiple times)" )
8994
90- cmd .Flags (). StringVar ( & options . PackageName , "package-name " , "" ,
91- "explicit package name to use instead of deriving from the directory name " )
95+ cmd .MarkFlagsOneRequired ( "component " , "lookaside-uri" )
96+ cmd . MarkFlagsMutuallyExclusive ( "component" , "lookaside-uri " )
9297
9398 return cmd
9499}
@@ -117,18 +122,6 @@ func DownloadSources(env *azldev.Env, options *DownloadSourcesOptions) error {
117122 extractOpts = append (extractOpts , fedorasource .WithOutputDir (options .OutputDir ))
118123 }
119124
120- // Verify the 'sources' file exists before attempting downloads.
121- sourcesPath := filepath .Join (options .Directory , "sources" )
122-
123- sourcesExists , err := fileutils .Exists (env .FS (), sourcesPath )
124- if err != nil {
125- return fmt .Errorf ("failed to check for sources file at %#q:\n %w" , sourcesPath , err )
126- }
127-
128- if ! sourcesExists {
129- return fmt .Errorf ("no 'sources' file found in %#q" , options .Directory )
130- }
131-
132125 // Try each lookaside base URI until one succeeds.
133126 var downloadErr error
134127
@@ -155,7 +148,11 @@ func DownloadSources(env *azldev.Env, options *DownloadSourcesOptions) error {
155148 outputDir = options .OutputDir
156149 }
157150
158- absOutputDir , _ := filepath .Abs (outputDir )
151+ absOutputDir , absErr := filepath .Abs (outputDir )
152+ if absErr != nil {
153+ absOutputDir = outputDir
154+ }
155+
159156 slog .Info ("Sources downloaded successfully" , "outputDir" , absOutputDir )
160157
161158 return nil
@@ -185,32 +182,28 @@ func createLookasideDownloader(env *azldev.Env) (fedorasource.FedoraSourceDownlo
185182}
186183
187184// resolveDownloadParams determines the package name and lookaside URIs.
185+ // In component mode, both are resolved from the component's config.
186+ // In standalone mode, lookaside URIs come from the flag and the package name
187+ // is derived from the directory basename.
188188func resolveDownloadParams (
189189 env * azldev.Env , options * DownloadSourcesOptions ,
190190) (packageName string , lookasideBaseURIs []string , err error ) {
191- packageName , err = resolvePackageName (options )
192- if err != nil {
193- return "" , nil , err
194- }
195-
191+ // Standalone mode: --lookaside-uri provided.
196192 if len (options .LookasideBaseURIs ) > 0 {
197- return packageName , options .LookasideBaseURIs , nil
198- }
193+ packageName , err = resolvePackageNameFromDir (options )
194+ if err != nil {
195+ return "" , nil , err
196+ }
199197
200- lookasideBaseURI , err := resolveLookasideURI (env )
201- if err != nil {
202- return "" , nil , err
198+ return packageName , options .LookasideBaseURIs , nil
203199 }
204200
205- return packageName , []string {lookasideBaseURI }, nil
201+ // Component mode: --component provided.
202+ return resolveFromComponent (env , options )
206203}
207204
208- // resolvePackageName determines the package name from the --package-name flag or directory name.
209- func resolvePackageName (options * DownloadSourcesOptions ) (string , error ) {
210- if options .PackageName != "" {
211- return options .PackageName , nil
212- }
213-
205+ // resolvePackageNameFromDir derives the package name from the directory basename.
206+ func resolvePackageNameFromDir (options * DownloadSourcesOptions ) (string , error ) {
214207 absDir , err := filepath .Abs (options .Directory )
215208 if err != nil {
216209 return "" , fmt .Errorf ("failed to resolve absolute path for %#q:\n %w" , options .Directory , err )
@@ -223,34 +216,54 @@ func resolvePackageName(options *DownloadSourcesOptions) (string, error) {
223216 return packageName , nil
224217}
225218
226- // resolveLookasideURI finds the lookaside base URI by checking the default distro first,
227- // then following the upstream distro reference if needed.
228- func resolveLookasideURI (env * azldev.Env ) (string , error ) {
229- distroDef , distroVersionDef , err := env .Distro ()
219+ // resolveFromComponent resolves both the package name and lookaside URI
220+ // from a component's configuration.
221+ func resolveFromComponent (
222+ env * azldev.Env , options * DownloadSourcesOptions ,
223+ ) (packageName string , lookasideBaseURIs []string , err error ) {
224+ resolver := components .NewResolver (env )
225+
226+ filter := & components.ComponentFilter {
227+ ComponentNamePatterns : []string {options .ComponentName },
228+ }
229+
230+ comps , err := resolver .FindComponents (filter )
230231 if err != nil {
231- return "" , fmt .Errorf ("failed to resolve default distro:\n %w" , err )
232+ return "" , nil , fmt .Errorf ("failed to resolve component %#q:\n %w" ,
233+ options .ComponentName , err )
232234 }
233235
234- // If the default distro itself has a lookaside URI, use it directly.
235- if distroDef . LookasideBaseURI != "" {
236- return distroDef . LookasideBaseURI , nil
236+ if comps . Len () == 0 {
237+ return "" , nil , fmt . Errorf ( "component %#q not found" ,
238+ options . ComponentName )
237239 }
238240
239- // Otherwise, follow the upstream distro reference from the default component config.
240- upstreamRef := distroVersionDef .DefaultComponentConfig .Spec .UpstreamDistro
241- if upstreamRef .Name == "" {
242- return "" , errors .New ("no lookaside base URI configured for the default distro, " +
243- "and no upstream distro reference found; use --lookaside-uri to specify one" )
241+ if comps .Len () != 1 {
242+ return "" , nil , fmt .Errorf (
243+ "expected exactly one component for %#q, got %d" ,
244+ options .ComponentName , comps .Len ())
245+ }
246+
247+ component := comps .Components ()[0 ]
248+
249+ // Derive package name from the component's upstream-name or component name.
250+ packageName = component .GetName ()
251+ if upstreamName := component .GetConfig ().Spec .UpstreamName ; upstreamName != "" {
252+ packageName = upstreamName
244253 }
245254
246- upstreamDef , _ , err := env . ResolveDistroRef ( upstreamRef )
255+ distro , err := sourceproviders . ResolveDistro ( env , component )
247256 if err != nil {
248- return "" , fmt .Errorf ("failed to resolve upstream distro %#q:\n %w" , upstreamRef .Name , err )
257+ return "" , nil , fmt .Errorf (
258+ "failed to resolve distro for component %#q:\n %w" ,
259+ options .ComponentName , err )
249260 }
250261
251- if upstreamDef .LookasideBaseURI == "" {
252- return "" , fmt .Errorf ("no lookaside base URI configured for upstream distro %#q" , upstreamRef .Name )
262+ if distro .Definition .LookasideBaseURI == "" {
263+ return "" , nil , fmt .Errorf (
264+ "no lookaside base URI configured for distro %#q" ,
265+ distro .Ref .Name )
253266 }
254267
255- return upstreamDef . LookasideBaseURI , nil
268+ return packageName , [] string { distro . Definition . LookasideBaseURI } , nil
256269}
0 commit comments