static void CollectGarbage(Log log, string dir, double days, bool hasLog = false) { if (!Directory.Exists(dir)) { return; } foreach (var f in Directory.EnumerateFiles(dir)) { using (new FileLock(log, f)) { var timeWrite = File.GetLastWriteTimeUtc(f); var timeNow = DateTime.UtcNow; if ((timeNow - timeWrite).TotalDays < days) { continue; } if (!hasLog) { log.WriteLine("stuff: Collecting garbage", ConsoleColor.Blue); hasLog = true; } Disk.DeleteFile(log, f); } } }
public static string GetFile(Log log, string url) { var dst = GetFileName(url); // 1) Early out if the file exists locally if (File.Exists(dst)) { Disk.TouchFile(log, dst); return(dst); } Disk.CreateDirectory(log, StuffDirectory); try { // Use a set to avoid repeating errors var errors = new HashSet <string>(); for (int tries = 0;; tries++) { // 2) Download the file from URL log.WriteLine("Downloading " + url + ( tries > 0 ? " (retry " + tries + "...)" : null ), ConsoleColor.Blue); try { using (var client = new StuffWebClient()) client.DownloadFile(url, dst); return(dst); } catch (Exception e) { // Fail the 10th time, or unless WebException if (tries >= 10 || !(e is WebException)) { // Print previous errors, before rethrowing foreach (var s in errors) { log.Error(s); } throw; } errors.Add(e.Message); Thread.Sleep(500); } } } catch { Disk.DeleteFile(log, dst); throw; } }
void InstallItem(KeyValuePair <string, object> item) { var itemKey = item.Key.Replace('/', Path.DirectorySeparatorChar); var components = itemKey.Split(Path.DirectorySeparatorChar); if (components.Contains(".") || components.Contains("..")) { throw new FormatException(item.Key + ": '.' or '..' are not valid in directory names"); } var itemFile = Path.Combine(_parentDirectory, ".uno", "stuff", itemKey); var targetDir = Path.Combine(_parentDirectory, itemKey); var itemValue = item.Value?.ToString(); if (string.IsNullOrEmpty(itemValue) || IsItemUpToDate(Log, targetDir, itemFile, itemValue, _flags)) { return; } using (new FileLock(Log, itemFile, DownloadCache.GetFileName(itemValue))) { if (IsItemUpToDate(Log, targetDir, itemFile, itemValue, _flags)) { return; } for (int tries = 0;; tries++) { Log.Verbose("Extracting " + targetDir.ToRelativePath().Quote(), ConsoleColor.DarkGray); // Support local files (e.g. from .STUFF-UPLOAD files) var localFile = Path.Combine(_parentDirectory, itemValue); var isLocal = File.Exists(localFile); var file = isLocal ? localFile : DownloadCache.GetFile(Log, itemValue); Disk.DeleteDirectory(Log, targetDir); Disk.CreateDirectory(Log, targetDir); try { if (PlatformDetection.IsWindows) { LongPathZipFile.ExtractToDirectory(file, targetDir); } else { // Use system tar/unzip to preserve file permissions and links // (ZipFile doesn't handle this) if (Path.GetFileName(file).ToUpper().EndsWith(".TAR.GZ")) { Shell.Untar(Log, file, targetDir); } else { Shell.Unzip(Log, file, targetDir); } // Make sure files extracted are writable so we can touch them Shell.Chmod(Log, "+w", targetDir); Disk.TouchAllFiles(Log, targetDir); } Disk.CreateDirectory(Log, Path.GetDirectoryName(itemFile)); File.WriteAllText(itemFile, itemValue); break; } catch (UnauthorizedAccessException) { // Don't try more if we get this throw; } catch { // Delete any installed files Disk.DeleteFile(Log, itemFile); Disk.DeleteDirectory(Log, targetDir); if (isLocal) { throw; } // Delete the cached download too Disk.DeleteFile(Log, file); // Redownload, and try just one more time to be sure // This might fix the problem if the cached file was corrupt if (tries > 0) { throw; } Thread.Sleep(150); } } } }