Exemplo n.º 1
0
        protected override Task <object> RemoteExecuteAsync(IRemoteOperationExecutionContext context)
        {
            var sourcePath = context.ResolvePath(this.SourceDirectory);

            this.LogInformation($"Finding matching files in {sourcePath}...");
            if (!DirectoryEx.Exists(sourcePath))
            {
                this.LogError($"Directory {sourcePath} does not exist.");
                return(Complete);
            }

            var mask    = new MaskingContext(this.Includes, this.Excludes);
            var matches = DirectoryEx.GetFileSystemInfos(sourcePath, mask)
                          .OfType <SlimFileInfo>()
                          .Where(f => f.FullName.EndsWith(".sql", StringComparison.OrdinalIgnoreCase))
                          .ToList();

            if (matches.Count == 0)
            {
                this.LogError($"No matching .sql files were found in {sourcePath}.");
                return(Complete);
            }

            var outputFileName = context.ResolvePath(this.OutputFile);

            DirectoryEx.Create(PathEx.GetDirectoryName(outputFileName));

            using (var buffer = new TemporaryStream())
            {
                using (var zip = new ZipArchive(buffer, ZipArchiveMode.Create, true))
                {
                    foreach (var f in matches)
                    {
                        var entryName = getEntryName(f.FullName);
                        this.LogDebug($"Adding {entryName}...");
                        zip.CreateEntryFromFile(f.FullName, entryName, CompressionLevel.Optimal);
                    }
                }

                buffer.Position = 0;

                using (var outputStream = FileEx.Open(outputFileName, FileMode.Create, FileAccess.Write, FileShare.None, FileOptions.SequentialScan))
                {
                    using (var inedoSqlStream = typeof(BundleSqlScriptsOperation).Assembly.GetManifestResourceStream("Inedo.Extensions.SqlServer.Operations.inedosql.exe"))
                    {
                        inedoSqlStream.CopyTo(outputStream);
                    }

                    buffer.CopyTo(outputStream);
                }
            }

            this.LogInformation($"{outputFileName} created.");
            return(Complete);

            string getEntryName(string fullName) => fullName.Substring(0, sourcePath.Length).TrimStart('\\', '/').Replace('\\', '/');
        }
Exemplo n.º 2
0
        public override async Task ExecuteAsync(IOperationExecutionContext context)
        {
            var sourceDirectory = context.ResolvePath(this.SourceDirectory);

            this.LogDebug($"Deleting files from {sourceDirectory}...");

            var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>().ConfigureAwait(false);

            if (!await fileOps.DirectoryExistsAsync(sourceDirectory).ConfigureAwait(false))
            {
                this.LogInformation(sourceDirectory + " does not exist.");
                return;
            }

            var mask = new MaskingContext(this.Includes, this.Excludes);

            // Optimization for clearing a folder
            if (mask.Includes.FirstOrDefault() == "**" && !mask.Excludes.Any() && !this.VerboseLogging)
            {
                this.LogDebug("Mask indicates that files and directories should be deleted recursively, clearing directory...");
                await fileOps.ClearDirectoryAsync(sourceDirectory).ConfigureAwait(false);

                this.LogInformation("Directory cleared.");
                return;
            }

            // Get the matches and make sure the root is not included
            // Sort by the number of directory separators in descending order so subdirs are deleted first
            var files = (await fileOps.GetFileSystemInfosAsync(sourceDirectory, mask).ConfigureAwait(false))
                        .OrderByDescending(m => m.FullName.Where(c => c == '/' || c == '\\').Count())
                        .ToList();

            var filesToDelete = files
                                .OfType <SlimFileInfo>()
                                .Select(e => e.FullName)
                                .ToArray();

            var directoriesToDelete = files
                                      .OfType <SlimDirectoryInfo>()
                                      .Select(e => e.FullName)
                                      .ToArray();

            if (this.VerboseLogging)
            {
                foreach (var fileName in filesToDelete)
                {
                    this.LogDebug($"Deleting file: {fileName}");
                }
            }

            await fileOps.DeleteFilesAsync(filesToDelete).ConfigureAwait(false);

            if (this.VerboseLogging)
            {
                foreach (var dirName in directoriesToDelete)
                {
                    this.LogDebug($"Deleting directory: {dirName}");
                }
            }

            await fileOps.DeleteDirectoriesAsync(directoriesToDelete).ConfigureAwait(false);

            this.LogInformation($"Deleted {filesToDelete.Length} files and {directoriesToDelete.Length} directories.");
        }
Exemplo n.º 3
0
        public override async Task ExecuteAsync(IOperationExecutionContext context)
        {
            var sourcePath     = context.ResolvePath(this.SourceDirectory);
            var maskingContext = new MaskingContext(this.Includes, this.Excludes);

            this.LogDebug($"Searching for files matching {maskingContext.ToString().Replace(Environment.NewLine, ", ")} in {sourcePath}...");

            var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>();

            var matches = (await fileOps.GetFileSystemInfosAsync(context.ResolvePath(this.SourceDirectory), new MaskingContext(this.Includes, this.Excludes)))
                          .OfType <SlimFileInfo>()
                          .ToList();

            if (matches.Count == 0)
            {
                this.LogWarning("No matching files found.");
                return;
            }

            this.LogDebug($"Found {matches.Count} matching files.");

            foreach (var projectFile in matches)
            {
                try
                {
                    this.LogDebug($"Reading {projectFile.FullName}...");

                    XDocument xdoc;
                    using (var stream = await fileOps.OpenFileAsync(projectFile.FullName, FileMode.Open, FileAccess.Read))
                    {
                        xdoc = XDocument.Load(stream);
                    }

                    this.LogDebug($"{projectFile.FullName} loaded.");

                    if (xdoc.Root.Name.LocalName != "Project")
                    {
                        this.LogError($"{projectFile.FullName} is not a valid project file; root element is \"{xdoc.Root.Name.LocalName}\", expected \"Project\".");
                        continue;
                    }

                    this.LogInformation($"Setting Version in {projectFile.FullName} to {this.Version}...");
                    UpdateOrAdd(xdoc, "Version", this.Version);
                    if (!string.IsNullOrWhiteSpace(this.AssemblyVersion))
                    {
                        this.LogInformation($"Setting AssemblyVersion in {projectFile.FullName} to {this.AssemblyVersion}...");
                        UpdateOrAdd(xdoc, "AssemblyVersion", this.AssemblyVersion);
                    }

                    if (!string.IsNullOrWhiteSpace(this.FileVersion))
                    {
                        this.LogInformation($"Setting FileVersion in {projectFile.FullName} to {this.FileVersion}...");
                        UpdateOrAdd(xdoc, "FileVersion", this.FileVersion);
                    }

                    if (!string.IsNullOrWhiteSpace(this.PackageVersion))
                    {
                        this.LogInformation($"Setting PackageVersion in {projectFile.FullName} to {this.PackageVersion}...");
                        UpdateOrAdd(xdoc, "PackageVersion", this.PackageVersion);
                    }

                    this.LogDebug($"Writing {projectFile.FullName}...");

                    using (var stream = await fileOps.OpenFileAsync(projectFile.FullName, FileMode.Create, FileAccess.Write))
                    {
                        xdoc.Save(stream);
                    }

                    this.LogDebug($"{projectFile.FullName} saved.");
                }
                catch (Exception ex)
                {
                    this.LogError($"Unable to update {projectFile.FullName}: {ex.Message}");
                }
            }
        }
Exemplo n.º 4
0
        public override async Task <PersistedConfiguration> CollectAsync(IOperationCollectionContext context)
        {
            var fileOps = context.Agent.GetService <IFileOperationsExecuter>();

            var client = new ProGetClient(this.Template.FeedUrl, this.Template.FeedName, this.Template.UserName, this.Template.Password, this);

            try
            {
                var packageId = PackageName.Parse(this.Template.PackageName);

                var packageInfo = await client.GetPackageInfoAsync(packageId).ConfigureAwait(false);

                var version = new ProGetPackageVersionSpecifier(this.Template.PackageVersion).GetBestMatch(packageInfo.versions);
                if (version == null)
                {
                    this.LogError($"Package {this.Template.PackageName} does not have a version {this.Template.PackageVersion}.");
                    return(null);
                }

                this.LogInformation($"Resolved package version is {version}.");

                if (!await fileOps.DirectoryExistsAsync(this.Template.TargetDirectory).ConfigureAwait(false))
                {
                    this.LogInformation(this.Template.TargetDirectory + " does not exist.");
                    return(new ProGetPackageConfiguration
                    {
                        TargetDirectory = this.Template.TargetDirectory
                    });
                }

                var mask = new MaskingContext(this.Template.Includes, this.Template.Excludes);

                this.LogInformation(this.Template.TargetDirectory + " exists; getting remote file list...");

                var remoteFileList = await fileOps.GetFileSystemInfosAsync(this.Template.TargetDirectory, mask).ConfigureAwait(false);

                var remoteFiles = new Dictionary <string, SlimFileSystemInfo>(remoteFileList.Count, StringComparer.OrdinalIgnoreCase);

                foreach (var file in remoteFileList)
                {
                    var relativeName = file.FullName.Substring(this.Template.TargetDirectory.Length).Replace('\\', '/').Trim('/');
                    if (file is SlimDirectoryInfo)
                    {
                        relativeName += "/";
                    }

                    remoteFiles.Add(relativeName, file);
                }

                remoteFileList = null; // async GC optimization

                this.LogDebug($"{this.Template.TargetDirectory} contains {remoteFiles.Count} file system entries.");

                this.LogInformation($"Connecting to {this.Template.FeedUrl} to get metadata for {this.Template.PackageName}:{version}...");
                var versionInfo = await client.GetPackageVersionInfoAsync(packageId, version).ConfigureAwait(false);

                if (versionInfo.fileList == null)
                {
                    this.LogError("File list is unavailable for this package; it may be an orphaned entry.");
                    return(null);
                }

                this.LogDebug($"Package contains {versionInfo.fileList.Length} file system entries.");

                foreach (var entry in versionInfo.fileList)
                {
                    var relativeName = entry.name;
                    if (!mask.IsMatch(relativeName))
                    {
                        continue;
                    }

                    var file = remoteFiles.GetValueOrDefault(relativeName);
                    if (file == null)
                    {
                        this.LogInformation($"Entry {relativeName} is not present in {this.Template.TargetDirectory}.");
                        return(new ProGetPackageConfiguration
                        {
                            TargetDirectory = this.Template.TargetDirectory
                        });
                    }

                    if (!entry.name.EndsWith("/"))
                    {
                        var fileInfo = (SlimFileInfo)file;
                        if (entry.size != fileInfo.Size || entry.date != fileInfo.LastWriteTimeUtc)
                        {
                            this.LogInformation($"File {relativeName} in {this.Template.TargetDirectory} is different from file in package.");
                            this.LogDebug($"Source info: {entry.size} bytes, {entry.date} timestamp");
                            this.LogDebug($"Target info: {fileInfo.Size} bytes, {fileInfo.LastWriteTimeUtc} timestamp");
                            return(new ProGetPackageConfiguration
                            {
                                TargetDirectory = this.Template.TargetDirectory
                            });
                        }
                    }
                }

                if (this.Template.DeleteExtra)
                {
                    foreach (var name in remoteFiles.Keys)
                    {
                        if (!versionInfo.fileList.Any(entry => entry.name == name))
                        {
                            this.LogInformation($"File {name} in {this.Template.TargetDirectory} does not exist in package.");
                            return(new ProGetPackageConfiguration
                            {
                                TargetDirectory = this.Template.TargetDirectory
                            });
                        }
                    }
                }

                this.LogInformation($"All package files and directories are present in {this.Template.TargetDirectory}.");
                return(new ProGetPackageConfiguration
                {
                    Current = true,
                    TargetDirectory = this.Template.TargetDirectory
                });
            }
            catch (ProGetException ex)
            {
                this.LogError(ex.FullMessage);
                return(null);
            }
        }
        protected override Task <object> RemoteExecuteAsync(IRemoteOperationExecutionContext context)
        {
            if (this.ReadOnly ?? this.Hidden ?? this.System == null)
            {
                this.LogWarning("No file attributes have been specified.");
                return(Complete);
            }

            var mask       = new MaskingContext(this.Includes, this.Excludes);
            var sourcePath = context.ResolvePath(this.SourceDirectory);

            this.LogInformation($"Getting list of files in {sourcePath} matching {mask}...");
            var matches = DirectoryEx.GetFileSystemInfos(sourcePath, mask)
                          .OfType <SlimFileInfo>()
                          .ToList();

            if (matches.Count == 0)
            {
                this.LogWarning("No files match the specified mask.");
                return(Complete);
            }

            FileAttributes attributesToChange = 0;

            if (this.ReadOnly.HasValue)
            {
                attributesToChange |= FileAttributes.ReadOnly;
            }
            if (this.Hidden.HasValue)
            {
                attributesToChange |= FileAttributes.Hidden;
            }
            if (this.System.HasValue)
            {
                attributesToChange |= FileAttributes.System;
            }

            FileAttributes attributeValues = 0;

            if (this.ReadOnly.GetValueOrDefault())
            {
                attributeValues |= FileAttributes.ReadOnly;
            }
            if (this.Hidden.GetValueOrDefault())
            {
                attributeValues |= FileAttributes.Hidden;
            }
            if (this.System.GetValueOrDefault())
            {
                attributeValues |= FileAttributes.System;
            }

            if (this.VerboseLogging)
            {
                this.LogDebug("Attributes to change: " + attributesToChange);
                this.LogDebug("Attribute values: " + attributeValues);
            }

            this.LogDebug($"Found {matches.Count} matching files.");
            this.LogInformation("Applying attributes...");
            foreach (var file in matches)
            {
                context.CancellationToken.ThrowIfCancellationRequested();

                var attributes = file.Attributes;

                if (((attributes & attributesToChange) ^ attributeValues) != 0)
                {
                    attributes &= ~attributesToChange;
                    attributes |= attributeValues;
                    if (this.VerboseLogging)
                    {
                        this.LogDebug("Changing " + file.FullName + "...");
                    }
                    FileEx.SetAttributes(file.FullName, attributes);
                }
            }

            this.LogInformation("Attributes applied.");

            return(Complete);
        }