예제 #1
0
        protected static async Task CopyFilesAsync(IFileOperationsExecuter fileOps, string sourceDirectory, string targetDirectory, bool keepInternals = false)
        {
            if (!await fileOps.DirectoryExistsAsync(sourceDirectory).ConfigureAwait(false))
            {
                return;
            }

            char separator = fileOps.DirectorySeparator;

            var infos = await fileOps.GetFileSystemInfosAsync(sourceDirectory, keepInternals?MaskingContext.IncludeAll : new MaskingContext(new[] { "**" }, new[] { "**" + separator + ".git**", ".git**" })).ConfigureAwait(false);

            var directoriesToCreate = infos.OfType <SlimDirectoryInfo>().Select(d => CombinePaths(targetDirectory, d.FullName.Substring(sourceDirectory.Length), separator)).ToArray();
            var relativeFileNames   = infos.OfType <SlimFileInfo>().Select(f => f.FullName.Substring(sourceDirectory.Length).TrimStart(separator)).ToArray();

            await fileOps.CreateDirectoryAsync(targetDirectory).ConfigureAwait(false);

            foreach (string folder in directoriesToCreate)
            {
                await fileOps.CreateDirectoryAsync(folder).ConfigureAwait(false);
            }

            await fileOps.FileCopyBatchAsync(
                sourceDirectory,
                relativeFileNames,
                targetDirectory,
                relativeFileNames,
                true,
                true
                ).ConfigureAwait(false);
        }
예제 #2
0
        private async Task TransferFileAsync(IFileOperationsExecuter sourceFileOps, SlimFileInfo sourceFile, IFileOperationsExecuter targetFileOps, SlimFileSystemInfo target, string targetDirectory)
        {
            if (target == null)
            {
                if (this.VerboseLogging)
                {
                    this.LogDebug($"{sourceFile.Name} does not exist in {targetDirectory}.");
                }
            }

            var targetFile = target as SlimFileInfo;

            if (targetFile != null)
            {
                this.LogDebug($"{sourceFile.Name} already exists in {targetDirectory}.");

                this.LogDebug($"Source timestamp: {sourceFile.LastWriteTimeUtc}, Target timestamp: {targetFile.LastWriteTimeUtc}");
                this.LogDebug($"Source size: {sourceFile.Size}, Target size: {targetFile.Size}");
                if (sourceFile.LastWriteTimeUtc == targetFile.LastWriteTimeUtc && sourceFile.Size == targetFile.Size)
                {
                    this.LogDebug($"Size and timestamp are the same; skipping {sourceFile.Name}...");
                    return;
                }
            }
            else if (target != null)
            {
                this.LogDebug($"{sourceFile.Name} is a file in {sourceFile.DirectoryName}, but a directory in {targetDirectory}.");

                this.LogDebug($"Deleting directory {target.FullName}...");
                await targetFileOps.DeleteDirectoriesAsync(new[] { target.FullName }).ConfigureAwait(false);
            }
            else
            {
                if (!string.IsNullOrEmpty(targetDirectory))
                {
                    await targetFileOps.CreateDirectoryAsync(targetDirectory).ConfigureAwait(false);
                }
            }

            var targetFileName = PathEx.Combine(targetDirectory, sourceFile.Name).Replace(sourceFileOps.DirectorySeparator, targetFileOps.DirectorySeparator);

            this.LogDebug($"Transferring {sourceFile.Name} to {targetDirectory}...");

            using (var sourceStream = await sourceFileOps.OpenFileAsync(sourceFile.FullName, FileMode.Open, FileAccess.Read).ConfigureAwait(false))
                using (var targetStream = await targetFileOps.OpenFileAsync(targetFileName, FileMode.Create, FileAccess.Write).ConfigureAwait(false))
                {
                    await sourceStream.CopyToAsync(targetStream).ConfigureAwait(false);
                }
        }
        private async Task CopyDirectoryAsync(IFileOperationsExecuter fileOps, string sourcePath, string targetPath, IOperationExecutionContext context)
        {
            if (!await fileOps.DirectoryExistsAsync(sourcePath).ConfigureAwait(false))
            {
                this.LogWarning($"Source directory {sourcePath} does not exist.");
                return;
            }

            var infos = await fileOps.GetFileSystemInfosAsync(
                sourcePath,
                new MaskingContext(this.Includes, this.Excludes)
                ).ConfigureAwait(false);

            var files = infos.OfType <SlimFileInfo>();

            foreach (var file in files)
            {
                context.CancellationToken.ThrowIfCancellationRequested();

                var targetFileName = PathEx.Combine(targetPath, file.FullName.Substring(sourcePath.Length).TrimStart('/', '\\'));
                if (this.VerboseLogging)
                {
                    this.LogDebug($"Copying {file.FullName} to {targetFileName}...");
                }

                try
                {
                    if (!this.Overwrite && await fileOps.FileExistsAsync(targetFileName).ConfigureAwait(false))
                    {
                        this.LogError($"Target file {targetFileName} already exists and overwrite is set to false.");
                        continue;
                    }

                    await fileOps.CreateDirectoryAsync(file.DirectoryName).ConfigureAwait(false);

                    await fileOps.CopyFileAsync(file.FullName, targetFileName, this.Overwrite).ConfigureAwait(false);

                    this.filesCopied++;
                }
                catch (Exception ex)
                {
                    this.LogError($"Cannot copy {file.FullName}: {ex.Message}");
                }
            }

            var dirs = infos.OfType <SlimDirectoryInfo>();

            foreach (var dir in dirs)
            {
                context.CancellationToken.ThrowIfCancellationRequested();

                var targetDir = PathEx.Combine(targetPath, dir.FullName.Substring(sourcePath.Length).TrimStart('/', '\\'));
                if (this.VerboseLogging)
                {
                    this.LogDebug($"Creating directory {targetDir}...");
                }

                await fileOps.CreateDirectoryAsync(targetDir).ConfigureAwait(false);

                this.directoriesCopied++;
            }
        }
예제 #4
0
        private async Task LockRegistryAsync(IFileOperationsExecuter fileOps, CancellationToken cancellationToken)
        {
            var fileName = fileOps.CombinePath(this.RegistryRoot, ".lock");

            var lockDescription = "Locked by " + SDK.ProductName;
            var lockToken       = Guid.NewGuid().ToString();

TryAgain:
            var fileInfo = await getFileInfoAsync().ConfigureAwait(false);

            string lastToken = null;

            while (fileInfo.Item1 != null && DateTime.UtcNow - fileInfo.Item1.LastWriteTimeUtc <= new TimeSpan(0, 0, 10))
            {
                if ((lastToken == null || !string.Equals(lastToken, fileInfo.Item3)) && fileInfo.Item3 != null)
                {
                    this.logger?.LogDebug("Package registry is locked: " + fileInfo.Item2);
                    lastToken = fileInfo.Item3;
                }
                await Task.Delay(500, cancellationToken).ConfigureAwait(false);

                fileInfo = await getFileInfoAsync().ConfigureAwait(false);
            }

            // ensure registry root exists
            await fileOps.CreateDirectoryAsync(this.RegistryRoot).ConfigureAwait(false);

            try
            {
                // write out the lock info
                using (var lockStream = await fileOps.OpenFileAsync(fileName, FileMode.Create, FileAccess.Write).ConfigureAwait(false))
                    using (var writer = new StreamWriter(lockStream, InedoLib.UTF8Encoding))
                    {
                        writer.WriteLine(lockDescription);
                        writer.WriteLine(lockToken);
                    }

                // verify that we acquired the lock
                using (var lockStream = await fileOps.OpenFileAsync(fileName, FileMode.Open, FileAccess.Read).ConfigureAwait(false))
                    using (var reader = new StreamReader(lockStream, InedoLib.UTF8Encoding))
                    {
                        if (reader.ReadLine() != lockDescription)
                        {
                            goto TryAgain;
                        }

                        if (reader.ReadLine() != lockToken)
                        {
                            goto TryAgain;
                        }
                    }
            }
            catch (IOException ex)
            {
                this.logger?.LogDebug("Locking package registry failed: " + ex.Message);

                // file may be in use by other process
                goto TryAgain;
            }

            // at this point, lock is acquired provided everyone is following the rules
            this.LockToken = lockToken;

            async Task <(SlimFileInfo, string, string)> getFileInfoAsync()
            {
                try
                {
                    var info = await fileOps.GetFileInfoAsync(fileName).ConfigureAwait(false);

                    string description = null, token = null;
                    try
                    {
                        using (var lockStream = await fileOps.OpenFileAsync(fileName, FileMode.Open, FileAccess.Read).ConfigureAwait(false))
                            using (var reader = new StreamReader(lockStream, InedoLib.UTF8Encoding))
                            {
                                description = await reader.ReadLineAsync().ConfigureAwait(false);

                                token = await reader.ReadLineAsync().ConfigureAwait(false);
                            }
                    }
                    catch (IOException)
                    {
                    }

                    return(info, description, token);
                }
                catch (FileNotFoundException)
                {
                    return(null, null, null);
                }
                catch (DirectoryNotFoundException)
                {
                    return(null, null, null);
                }
            }
        }