src/Microsoft.DotNet.Darc/src/Darc/Operations/UpdateDependenciesOperation.cs
/// <summary>
/// Update local dependencies based on a specific channel.
/// </summary>
/// <param name="options">Command line options</param>
/// <returns>Process exit code.</returns>
Update local dependencies based on a specific channel.
Update local dependencies based on a specific channel .
public override async Task<int> ExecuteAsync()
        {
            try
            {
                DarcSettings darcSettings = darcSettings = LocalSettings.GetDarcSettings(_options, Logger);
                darcSettings.GitType = GitRepoType.GitHub;
                LocalSettings localSettings = LocalSettings.LoadSettingsFile();
                darcSettings.PersonalAccessToken = !string.IsNullOrEmpty(localSettings.GitHubToken) ?
                                                    localSettings.GitHubToken :
                                                    _options.GitHubPat;
                Remote remote = new Remote(darcSettings, Logger);
                Local local = new Local(LocalHelpers.GetGitDir(Logger), Logger);
                List<DependencyDetail> dependenciesToUpdate = new List<DependencyDetail>();
                bool someUpToDate = false;
                string finalMessage = $"Local dependencies updated from channel '{_options.Channel}'.";
                IEnumerable<DependencyDetail> dependencies = await local.GetDependenciesAsync(_options.Name);
                if (!dependencies.Any())
                {
                    Console.WriteLine("Found no dependencies to update.");
                    return Constants.ErrorCode;
                }
                if (!string.IsNullOrEmpty(_options.Name) && !string.IsNullOrEmpty(_options.Version))
                {
                    DependencyDetail dependency = dependencies.First();
                    dependency.Version = _options.Version;
                    dependenciesToUpdate.Add(dependency);
                    Console.WriteLine($"Updating '{dependency.Name}': '{dependency.Version}' => '{_options.Version}'");
                    finalMessage = $"Local dependency {_options.Name} updated to version '{_options.Version}'.";
                }
                else if (!string.IsNullOrEmpty(_options.PackagesFolder))
                {
                    try
                    {
                        dependenciesToUpdate.AddRange(GetDependenciesFromPackagesFolder(_options.PackagesFolder, dependencies));
                    }
                    catch (DarcException exc)
                    {
                        Logger.LogError(exc, $"Error: Failed to update dependencies based on folder '{_options.PackagesFolder}'");
                        return Constants.ErrorCode;
                    }
                    finalMessage = $"Local dependencies updated based on packages folder {_options.PackagesFolder}.";
                }
                else
                {
                    var channel = remote.GetChannelAsync(_options.Channel);
                    var repositoryUrisForQuery = dependencies.Select(dependency => dependency.RepoUri).ToHashSet();
                    ConcurrentDictionary<string, Task<Build>> getLatestBuildTaskDictionary = new ConcurrentDictionary<string, Task<Build>>();
                    Channel channelInfo = await channel;
                    if (channelInfo == null)
                    {
                        Console.WriteLine($"Could not find a channel named '{_options.Channel}'.");
                        return Constants.ErrorCode;
                    }
                    foreach (string repoToQuery in repositoryUrisForQuery)
                    {
                        var latestBuild = remote.GetLatestBuildAsync(repoToQuery, channelInfo.Id.Value);
                        getLatestBuildTaskDictionary.TryAdd(repoToQuery, latestBuild);
                    }
                    foreach (DependencyDetail dependency in dependencies)
                    {
                        Build build;
                        try
                        {
                            build = await getLatestBuildTaskDictionary[dependency.RepoUri];
                        }
                        catch (ApiErrorException e) when (e.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
                        {
                            Logger.LogTrace($"No build of '{dependency.RepoUri}' found on channel '{_options.Channel}'.");
                            continue;
                        }
                        Asset buildAsset = build.Assets.Where(asset => asset.Name.Equals(dependency.Name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                        if (buildAsset == null)
                        {
                            Logger.LogTrace($"Dependency '{dependency.Name}' not found in latest build of '{dependency.RepoUri}' on '{_options.Channel}', skipping.");
                            continue;
                        }
                        if (buildAsset.Version == dependency.Version &&
                            buildAsset.Name == dependency.Name &&
                            build.Repository == dependency.RepoUri &&
                            build.Commit == dependency.Commit)
                        {
                            someUpToDate = true;
                            continue;
                        }
                        DependencyDetail updatedDependency = new DependencyDetail
                        {
                            Branch = null,
                            Commit = build.Commit,
                            Name = buildAsset.Name,
                            RepoUri = build.Repository,
                            Version = buildAsset.Version
                        };
                        dependenciesToUpdate.Add(updatedDependency);
                        Console.WriteLine($"Updating '{dependency.Name}': '{dependency.Version}' => '{updatedDependency.Version}'" +
                            $" (from build '{build.BuildNumber}' of '{build.Repository}')");
                        if (buildAsset.Name != dependency.Name)
                        {
                            Console.WriteLine($"  Dependency name normalized to '{updatedDependency.Name}'");
                        }
                        dependenciesToUpdate.Add(updatedDependency);
                    }
                }
                if (!dependenciesToUpdate.Any())
                {
                    if (someUpToDate)
                    {
                        Console.WriteLine($"All dependencies are up to date.");
                        return Constants.SuccessCode;
                    }
                    else
                    {
                        Console.WriteLine($"Found no dependencies to update.");
                        return Constants.ErrorCode;
                    }
                }
                if (_options.DryRun)
                {
                    return Constants.SuccessCode;
                }
                await local.UpdateDependenciesAsync(dependenciesToUpdate, remote);
                Console.WriteLine(finalMessage);
                return Constants.SuccessCode;
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"Error: Failed to update dependencies to channel {_options.Channel}");
                return Constants.ErrorCode;
            }
        }
public override async Task < int > ExecuteAsync ( ) { try { DarcSettings darcSettings = darcSettings = LocalSettings . GetDarcSettings ( _options , Logger ) ; darcSettings . GitType = GitRepoType . GitHub ; LocalSettings localSettings = LocalSettings . LoadSettingsFile ( ) ; darcSettings . PersonalAccessToken = ! string . IsNullOrEmpty ( localSettings . GitHubToken ) ? localSettings . GitHubToken : _options . GitHubPat ; Remote remote = new Remote ( darcSettings , Logger ) ; Local local = new Local ( LocalHelpers . GetGitDir ( Logger ) , Logger ) ; List < DependencyDetail > dependenciesToUpdate = new List < DependencyDetail > ( ) ; bool someUpToDate = false ; string finalMessage = $" Local dependencies updated from channel ' { _options . Channel } '. " ; IEnumerable < DependencyDetail > dependencies = await local . GetDependenciesAsync ( _options . Name ) ; if ( ! dependencies . Any ( ) ) { Console . WriteLine ( " " ) ; return Constants . ErrorCode ; } if ( ! string . IsNullOrEmpty ( _options . Name ) && ! string . IsNullOrEmpty ( _options . Version ) ) { DependencyDetail dependency = dependencies . First ( ) ; dependency . Version = _options . Version ; dependenciesToUpdate . Add ( dependency ) ; Console . WriteLine ( $" Updating ' { dependency . Name } ': ' { dependency . Version } ' => ' { _options . Version } ' " ) ; finalMessage = $" Local dependency  { _options . Name }  updated to version ' { _options . Version } '. " ; } else if ( ! string . IsNullOrEmpty ( _options . PackagesFolder ) ) { try { dependenciesToUpdate . AddRange ( GetDependenciesFromPackagesFolder ( _options . PackagesFolder , dependencies ) ) ; } catch ( DarcException exc ) { Logger . LogError ( exc , $" Error: Failed to update dependencies based on folder ' { _options . PackagesFolder } ' " ) ; return Constants . ErrorCode ; } finalMessage = $" Local dependencies updated based on packages folder  { _options . PackagesFolder } . " ; } else { var channel = remote . GetChannelAsync ( _options . Channel ) ; var repositoryUrisForQuery = dependencies . Select ( dependency => dependency . RepoUri ) . ToHashSet ( ) ; ConcurrentDictionary < string , Task < Build > > getLatestBuildTaskDictionary = new ConcurrentDictionary < string , Task < Build > > ( ) ; Channel channelInfo = await channel ; if ( channelInfo == null ) { Console . WriteLine ( $" Could not find a channel named ' { _options . Channel } '. " ) ; return Constants . ErrorCode ; } foreach ( string repoToQuery in repositoryUrisForQuery ) { var latestBuild = remote . GetLatestBuildAsync ( repoToQuery , channelInfo . Id . Value ) ; getLatestBuildTaskDictionary . TryAdd ( repoToQuery , latestBuild ) ; } foreach ( DependencyDetail dependency in dependencies ) { Build build ; try { build = await getLatestBuildTaskDictionary [ dependency . RepoUri ] ; } catch ( ApiErrorException e ) when ( e . Response . StatusCode == System . Net . HttpStatusCode . NotFound ) { Logger . LogTrace ( $" No build of ' { dependency . RepoUri } ' found on channel ' { _options . Channel } '. " ) ; continue ; } Asset buildAsset = build . Assets . Where ( asset => asset . Name . Equals ( dependency . Name , StringComparison . OrdinalIgnoreCase ) ) . FirstOrDefault ( ) ; if ( buildAsset == null ) { Logger . LogTrace ( $" Dependency ' { dependency . Name } ' not found in latest build of ' { dependency . RepoUri } ' on ' { _options . Channel } ', skipping. " ) ; continue ; } if ( buildAsset . Version == dependency . Version && buildAsset . Name == dependency . Name && build . Repository == dependency . RepoUri && build . Commit == dependency . Commit ) { someUpToDate = true ; continue ; } DependencyDetail updatedDependency = new DependencyDetail { Branch = null , Commit = build . Commit , Name = buildAsset . Name , RepoUri = build . Repository , Version = buildAsset . Version } ; dependenciesToUpdate . Add ( updatedDependency ) ; Console . WriteLine ( $" Updating ' { dependency . Name } ': ' { dependency . Version } ' => ' { updatedDependency . Version } ' " + $"  (from build ' { build . BuildNumber } ' of ' { build . Repository } ') " ) ; if ( buildAsset . Name != dependency . Name ) { Console . WriteLine ( $"   Dependency name normalized to ' { updatedDependency . Name } ' " ) ; } dependenciesToUpdate . Add ( updatedDependency ) ; } } if ( ! dependenciesToUpdate . Any ( ) ) { if ( someUpToDate ) { Console . WriteLine ( $" All dependencies are up to date. " ) ; return Constants . SuccessCode ; } else { Console . WriteLine ( $" Found no dependencies to update. " ) ; return Constants . ErrorCode ; } } if ( _options . DryRun ) { return Constants . SuccessCode ; } await local . UpdateDependenciesAsync ( dependenciesToUpdate , remote ) ; Console . WriteLine ( finalMessage ) ; return Constants . SuccessCode ; } catch ( Exception e ) { Logger . LogError ( e , $" Error: Failed to update dependencies to channel  { _options . Channel } " ) ; return Constants . ErrorCode ; } }
Update local dependencies based on a specific channel.
Update local dependencies based on a specific channel .
// TODO: PAT only used for pulling the arcade eng/common dir, // so hardcoded to GitHub PAT right now. Must be more generic in the future. // First we need to figure out what to query for.  Load Version.Details.xml and // find all repository uris, optionally restricted by the input dependency parameter. // Start channel query. // Limit the number of BAR queries by grabbing the repo URIs and making a hash set. // Now walk dependencies again and attempt the update // No changes // TODO: Not needed, but not currently provided in Build info. Will be available on next rollout. // If casing changes, ensure that the dependency name gets updated. // Print out what we are going to do. // Notify on casing changes. // If we found some dependencies already up to date, // then we consider this a success. Otherwise, we didn't even // find matching dependencies so we should let the user know. // Now call the local updater to run the update
Process exit code.
Process exit code .
options
Command line options
Command line options