// Copy the source code
        public virtual void CopyUnixSrc(string baseOutputDir)
        {
            // Generate an Output directory name
            string outDir    = baseOutputDir;
            string outSrcDir = baseOutputDir;

            Con.WriteLine("BuildSrcKit for '{0}'...", this.IDString);
            Con.WriteLine("BuildSrcKit Output Dir = '{0}'.", outDir);

            string tsFile    = Path.Combine(outDir, "TimeStamp.txt");
            string timeStamp = Str.DateTimeToStrShort(BuildSoftwareList.ListCreatedDateTime);

            Con.WriteLine("timestamp={0}", timeStamp);

            if (Directory.Exists(outDir))
            {
            }
            else
            {
                Directory.CreateDirectory(outDir);
            }

            // Copy the source code
            foreach (string srcDirName in SrcDirNameList)
            {
                string srcFullPath  = Path.Combine(Paths.BaseDirName, srcDirName);
                string destFullPath = Path.Combine(outSrcDir, srcDirName);

                IO.CopyDir(srcFullPath, destFullPath, new IO.CopyDirPreCopyDelegate(CopySrcFilesDelegate), false, true, true, true, true);
            }
            IO.FileCopy(Path.Combine(Paths.BaseDirName, "CurrentBuild.txt"), Path.Combine(outSrcDir, "CurrentBuild.txt"), true, false);
        }
예제 #2
0
        public static void WriteBuildInfoToTextFile(int build, int version, string name, DateTime date, string filename)
        {
            using (StreamWriter w = new StreamWriter(filename))
            {
                w.WriteLine("BUILD_NUMBER {0}", build);
                w.WriteLine("VERSION {0}", version);
                w.WriteLine("BUILD_NAME {0}", name);
                w.WriteLine("BUILD_DATE {0}", Str.DateTimeToStrShort(date));

                w.Flush();
                w.Close();
            }
        }
예제 #3
0
        // Initialize
        static Paths()
        {
            // Starting date and time string
            Paths.StartDateTimeStr = Str.DateTimeToStrShort(Paths.StartDateTime);

            // Check whether the execution path is the bin directory in the VPN directory
            if (Paths.SolutionBinDirName.EndsWith(@"\bin", StringComparison.InvariantCultureIgnoreCase) == false)
            {
                throw new ApplicationException(string.Format("'{0}' is not a VPN bin directory.", Paths.SolutionBinDirName));
            }

            // Determine the Visual Studio solution file
            string slnFileName = Directory.EnumerateFiles(SolutionBaseDirName).Where(x => x.EndsWith(".sln")).Single();

            Paths.VisualStudioSolutionFileName = Path.Combine(SolutionBaseDirName, slnFileName);

            if (File.Exists(Paths.VisualStudioSolutionFileName) == false)
            {
                throw new ApplicationException(string.Format("'{0}' is not a VPN base directory.", Paths.SolutionBaseDirName));
            }

            // Get Microsoft SDK directory
            if (IntPtr.Size == 8)
            {
                Paths.MicrosoftSDKDir = IO.RemoteLastEnMark(Reg.ReadStr(RegRoot.LocalMachine, @"SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0", "InstallationFolder"));
            }
            else
            {
                Paths.MicrosoftSDKDir = IO.RemoteLastEnMark(Reg.ReadStr(RegRoot.LocalMachine, @"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0", "InstallationFolder"));
            }

            if (Str.IsEmptyStr(Paths.MicrosoftSDKDir))
            {
                throw new ApplicationException("Microsoft SDK not found.");
            }

            Paths.MicrosoftSDKBinDir = Path.Combine(Paths.MicrosoftSDKDir, @"bin\x86");

            if (File.Exists(Path.Combine(Paths.MicrosoftSDKBinDir, "rc.exe")) == false)
            {
                // rc.exe not found. Enum alternative sub directories
                string tmp = Path.GetDirectoryName(Paths.MicrosoftSDKBinDir);

                foreach (string subDir in Directory.EnumerateDirectories(tmp).OrderByDescending(x => x))
                {
                    string tmp2 = Path.Combine(tmp, subDir, "x86");

                    if (File.Exists(Path.Combine(tmp2, "rc.exe")))
                    {
                        Paths.MicrosoftSDKBinDir = tmp2;
                        break;
                    }
                }
            }

            // Get makecat.exe file name
            Paths.MakeCatFilename = Path.Combine(Paths.MicrosoftSDKBinDir, "makecat.exe");

            // Get the rc.exe file name
            Paths.RcFilename = Path.Combine(Paths.MicrosoftSDKBinDir, "rc.exe");

            // Get the cmd.exe file name
            Paths.CmdFileName = Path.Combine(Env.SystemDir, "cmd.exe");
            if (File.Exists(Paths.CmdFileName) == false)
            {
                throw new ApplicationException(string.Format("File '{0}' not found.", Paths.CmdFileName));
            }

            // Get the TMP directory
            Paths.TmpDirName = Path.Combine(Paths.SolutionBaseDirName, "tmp");
            if (Directory.Exists(Paths.TmpDirName) == false)
            {
                Directory.CreateDirectory(Paths.TmpDirName);
            }
        }
        // Build SrcKit
        public virtual bool BuildSrcKit(string baseOutputDir, bool debugMode)
        {
            // Generate an Output directory name
            string outDir    = Path.Combine(baseOutputDir, this.CrossLibName);
            string outSrcDir = Path.Combine(outDir, "src");

            Con.WriteLine("BuildSrcKit for '{0}'...", this.IDString);
            Con.WriteLine("CrossLib Name: '{0}'.", this.CrossLibName);
            Con.WriteLine("BuildSrcKit Output Dir = '{0}'.", outDir);

            string tsFile    = Path.Combine(outDir, "TimeStamp.txt");
            string timeStamp = Str.DateTimeToStrShort(BuildSoftwareList.ListCreatedDateTime);

            Con.WriteLine("timestamp={0}", timeStamp);

            if (Directory.Exists(outDir))
            {
                bool ok = false;
                // See TimeStamp.txt file if the directory already exists
                try
                {
                    string[] ts = File.ReadAllLines(tsFile);
                    if (ts[0] == timeStamp)
                    {
                        ok = true;
                    }
                }
                catch
                {
                }

                if (ok)
                {
                    Con.WriteLine("Skipped for '{0}'.", this.IDString);
                    return(false);
                }
            }
            else
            {
                Directory.CreateDirectory(outDir);
            }

            // Copy the source code
            foreach (string srcDirName in SrcDirNameList)
            {
                string srcFullPath  = Path.Combine(Paths.BaseDirName, srcDirName);
                string destFullPath = Path.Combine(outSrcDir, srcDirName);
                bool   delete_bom   = true;

                if (Str.InStr(srcDirName, "\\hamcore"))
                {
                    delete_bom = false;
                }

                IO.CopyDir(srcFullPath, destFullPath, new IO.CopyDirPreCopyDelegate(CopySrcFilesDelegate), false, true, true, delete_bom);
            }
            IO.FileCopy(Path.Combine(Paths.BaseDirName, "CurrentBuild.txt"), Path.Combine(outSrcDir, "CurrentBuild.txt"), true, false);
            IO.FileCopy(Path.Combine(Paths.BaseDirName, "GlobalConst.h"), Path.Combine(outSrcDir, "GlobalConst.h"), true, false);
            IO.FileCopy(Path.Combine(Paths.BaseDirName, @"DebugFiles\Replace.h"), Path.Combine(outSrcDir, "Replace.h"), true, false);
            IO.FileCopy(Path.Combine(Paths.BaseDirName, @"bin\BuiltHamcoreFiles\hamcore_unix\hamcore.se2"),
                        Path.Combine(outSrcDir, @"bin\hamcore.se2"), true, false);

            // Copy Crosslibs
            IO.CopyDir(Path.Combine(this.CrossLibBaseDir, this.CrossLibName), Path.Combine(outSrcDir, @"lib"),
                       delegate(FileInfo fi)
            {
                if (fi.DirectoryName.IndexOf(@".svn", StringComparison.InvariantCultureIgnoreCase) != -1)
                {
                    return(false);
                }
                return(true);
            }, false, true, true, false);

            // Generate Makefile for compilation
            byte[] makeFileDataForCross = Str.NormalizeCrlf(Str.Utf8Encoding.GetBytes(GenerateMakeFileForCompile(outSrcDir, debugMode, true).ToString()), new byte[] { 10, });
            byte[] makeFileDataForSelf  = Str.NormalizeCrlf(Str.Utf8Encoding.GetBytes(GenerateMakeFileForCompile(outSrcDir, debugMode, false).ToString()), new byte[] { 10, });

            string makeFileName = Path.Combine(outSrcDir, "Makefile");

            File.WriteAllBytes(makeFileName, makeFileDataForCross);

            // TimeStamp.txt
            File.WriteAllText(tsFile, timeStamp);

            // Create a tar.gz
            string tarGzFileName = Path.Combine(outSrcDir, this.SrcKitFileName);

            Con.WriteLine("Creating '{0}'...", tarGzFileName);
            List <string> files = new List <string>();

            foreach (string srcDirName in Util.CombineArray <string>(SrcDirNameList, new string[] { "lib" }))
            {
                string   dirFullPath = Path.Combine(outSrcDir, srcDirName);
                string[] fileList    = Directory.GetFiles(dirFullPath, "*",
                                                          srcDirName.Equals("lib", StringComparison.InvariantCultureIgnoreCase) ? SearchOption.TopDirectoryOnly : SearchOption.AllDirectories);
                foreach (string fileName in fileList)
                {
                    files.Add(fileName);
                }
            }
            files.Add(Path.Combine(outSrcDir, @"CurrentBuild.txt"));
            files.Add(Path.Combine(outSrcDir, @"bin\hamcore.se2"));
            files.Add(Path.Combine(outSrcDir, @"Replace.h"));
            files.Add(Path.Combine(outSrcDir, @"GlobalConst.h"));

            files.Sort();
            TarPacker tar = new TarPacker();

            foreach (string file in files)
            {
                byte[] fileData = File.ReadAllBytes(file);
                tar.AddFileSimple(@"src\" + IO.GetRelativeFileName(file, outSrcDir),
                                  fileData,
                                  0, fileData.Length, File.GetLastWriteTime(file), "0000750", "0000640");
            }
            tar.AddFileSimple(@"src\Makefile", makeFileDataForSelf, 0, makeFileDataForSelf.Length, DateTime.Now, "0000750", "0000640");
            tar.Finish();
            byte[] tarGzData = tar.CompressToGZip();
            File.WriteAllBytes(tarGzFileName, tarGzData);

            IO.MakeDir(Paths.ReleaseSrckitDir);
            File.WriteAllBytes(Path.Combine(Paths.ReleaseSrckitDir, this.SrcKitFileName), tarGzData);

            Con.WriteLine("Completed.");

            return(true);
        }
예제 #5
0
 // Get the DebugSnapshot directory name
 public static string GetDebugSnapstotDirName()
 {
     return(Path.Combine(Paths.DebugSnapshotBaseDir, Str.DateTimeToStrShort(BuildSoftwareList.ListCreatedDateTime)));
 }
예제 #6
0
        // Initialize
        static Paths()
        {
            // Starting date and time string
            Paths.StartDateTimeStr = Str.DateTimeToStrShort(Paths.StartDateTime);

            // Check whether the execution path is the bin directory in the VPN directory
            if (Paths.BinDirName.EndsWith(@"\bin", StringComparison.InvariantCultureIgnoreCase) == false)
            {
                throw new ApplicationException(string.Format("'{0}' is not a VPN bin directory.", Paths.BinDirName));
            }
            if (File.Exists(Paths.VPN4SolutionFileName) == false)
            {
                throw new ApplicationException(string.Format("'{0}' is not a VPN base directory.", Paths.BaseDirName));
            }

            // Get the VC++ directory
            // Visual Studio 2008
            if (IntPtr.Size == 4)
            {
                Paths.VisualStudioVCDir = IO.RemoteLastEnMark(Reg.ReadStr(RegRoot.LocalMachine, @"SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VC", "ProductDir"));
            }
            else
            {
                Paths.VisualStudioVCDir = IO.RemoteLastEnMark(Reg.ReadStr(RegRoot.LocalMachine, @"SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Setup\VC", "ProductDir"));
            }
            if (Str.IsEmptyStr(Paths.VisualStudioVCDir))
            {
                throw new ApplicationException("Visual C++ directory not found.\n");
            }
            if (Directory.Exists(Paths.VisualStudioVCDir) == false)
            {
                throw new ApplicationException(string.Format("Directory '{0}' not found.", Paths.VisualStudioVCDir));
            }

            // Get the VC++ batch file name
            Paths.VisualStudioVCBatchFileName = Path.Combine(Paths.VisualStudioVCDir, "vcvarsall.bat");
            if (File.Exists(Paths.VisualStudioVCBatchFileName) == false)
            {
                throw new ApplicationException(string.Format("File '{0}' not found.", Paths.VisualStudioVCBatchFileName));
            }

            bool x86_dir = false;

            // Get Microsoft SDK 6.0a directory
            if (IntPtr.Size == 4)
            {
                Paths.MicrosoftSDKDir = IO.RemoteLastEnMark(Reg.ReadStr(RegRoot.LocalMachine, @"SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v7.0A", "InstallationFolder"));
            }
            else
            {
                Paths.MicrosoftSDKDir = IO.RemoteLastEnMark(Reg.ReadStr(RegRoot.LocalMachine, @"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A", "InstallationFolder"));
            }

            // Get makecat.exe file name
            Paths.MakeCatFilename = Path.Combine(Paths.MicrosoftSDKDir, @"bin\" + (x86_dir ? @"x86\" : "") + "makecat.exe");

            // Get the rc.exe file name
            Paths.RcFilename = Path.Combine(Paths.MicrosoftSDKDir, @"bin\" + (x86_dir ? @"x86\" : "") + "rc.exe");

            // Get the cmd.exe file name
            Paths.CmdFileName = Path.Combine(Env.SystemDir, "cmd.exe");
            if (File.Exists(Paths.CmdFileName) == false)
            {
                throw new ApplicationException(string.Format("File '{0}' not found.", Paths.CmdFileName));
            }

            // Get .NET Framework 3.5 directory
            Paths.DotNetFramework35Dir = Path.Combine(Env.WindowsDir, @"Microsoft.NET\Framework\v4.0.30319");

            // Get msbuild.exe directory
            Paths.MSBuildFileName = Path.Combine(Paths.DotNetFramework35Dir, "MSBuild.exe");
            if (File.Exists(Paths.MSBuildFileName) == false)
            {
                throw new ApplicationException(string.Format("File '{0}' not found.", Paths.MSBuildFileName));
            }

            // Get the TMP directory
            Paths.TmpDirName = Path.Combine(Paths.BaseDirName, "tmp");
            if (Directory.Exists(Paths.TmpDirName) == false)
            {
                Directory.CreateDirectory(Paths.TmpDirName);
            }
        }
예제 #7
0
    // 1 つのディレクトリをバックアップする
    public async Task DoSingleDirBackupAsync(string srcDir, string destDir, CancellationToken cancel = default, string?ignoreDirNames = null)
    {
        DateTimeOffset now = DateTimeOffset.Now;

        FileSystemEntity[]? srcDirEnum = null;

        string[] ignoreDirNamesList = ignoreDirNames._NonNull()._Split(StringSplitOptions.RemoveEmptyEntries, ",", ";");

        FileMetadata?srcDirMetadata = null;

        bool noError = true;

        try
        {
            if (srcDir._IsSamei(destDir))
            {
                throw new CoresException($"srcDir == destDir. Directory path: '{srcDir}'");
            }

            srcDirMetadata = await Fs.GetDirectoryMetadataAsync(srcDir, cancel : cancel);

            srcDirEnum = (await Fs.EnumDirectoryAsync(srcDir, false, EnumDirectoryFlags.NoGetPhysicalSize, cancel)).OrderBy(x => x.Name, StrComparer.IgnoreCaseComparer).ToArray();

            FileSystemEntity[] destDirEnum = new FileSystemEntity[0];

            DirSuperBackupMetadata?destDirOldMetaData = null;

            DirSuperBackupMetadata destDirNewMetaData;

            // 宛先ディレクトリがすでに存在しているかどうか検査する
            if (await Fs.IsDirectoryExistsAsync(destDir, cancel))
            {
                destDirEnum = await Fs.EnumDirectoryAsync(destDir, false, EnumDirectoryFlags.NoGetPhysicalSize, cancel);

                // 宛先ディレクトリに存在するメタデータファイルのうち最新のファイルを取得する
                destDirOldMetaData = await GetLatestMetaDataFileNameAsync(destDir, destDirEnum, cancel);
            }
            else
            {
                // 宛先ディレクトリがまだ存在していない場合は作成する
                await Fs.CreateDirectoryAsync(destDir, FileFlags.BackupMode | FileFlags.AutoCreateDirectory, cancel);
            }

            // 宛先ディレクトリの日付情報のみ属性書き込みする
            try
            {
                await Fs.SetFileMetadataAsync(destDir, srcDirMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel);
            }
            catch
            {
                // 属性書き込みは失敗してもよい
            }

            // 新しいメタデータを作成する
            destDirNewMetaData             = new DirSuperBackupMetadata();
            destDirNewMetaData.FileList    = new List <DirSuperBackupMetadataFile>();
            destDirNewMetaData.TimeStamp   = now;
            destDirNewMetaData.DirMetadata = srcDirMetadata;
            destDirNewMetaData.DirList     = new List <string>();

            // 元ディレクトリに存在するサブディレクトリ名一覧をメタデータに追記する
            foreach (var subDir in srcDirEnum.Where(x => x.IsDirectory && x.IsCurrentOrParentDirectory == false))
            {
                // シンボリックリンクは無視する
                if (subDir.IsSymbolicLink == false)
                {
                    // 無視リストのいずれにも合致しない場合のみ
                    if (ignoreDirNamesList.Where(x => x._IsSamei(subDir.Name)).Any() == false)
                    {
                        destDirNewMetaData.DirList.Add(subDir.Name);
                    }
                }
            }

            // 元ディレクトリに存在するファイルを 1 つずつバックアップする
            var fileEntries = srcDirEnum.Where(x => x.IsFile);

            RefInt concurrentNum = new RefInt();

            AsyncLock SafeLock = new AsyncLock();

            await TaskUtil.ForEachAsync(Options.NumThreads, fileEntries, async (srcFile, taskIndex, cancel) =>
            {
                long?encryptedPhysicalSize = null;

                await Task.Yield();

                string destFilePath = Fs.PathParser.Combine(destDir, srcFile.Name);

                if (Options.EncryptPassword._IsNullOrZeroLen() == false)
                {
                    destFilePath += Consts.Extensions.CompressedXtsAes256;
                }

                FileMetadata?srcFileMetadata = null;

                concurrentNum.Increment();

                try
                {
                    srcFileMetadata = await Fs.GetFileMetadataAsync(srcFile.FullPath, cancel: cancel);

                    // このファイルと同一のファイル名がすでに宛先ディレクトリに物理的に存在するかどうか確認する
                    bool exists = await Fs.IsFileExistsAsync(destFilePath, cancel);

                    bool fileChangedOrNew = false;

                    if (exists)
                    {
                        // すでに宛先ディレクトリに存在する物理的なファイルのメタデータを取得する
                        FileMetadata destExistsMetadata = await Fs.GetFileMetadataAsync(destFilePath, cancel: cancel);

                        if (Options.EncryptPassword._IsNullOrZeroLen())
                        {
                            // 暗号化なし
                            // ファイルサイズを比較する
                            if (destExistsMetadata.Size != srcFile.Size)
                            {
                                // ファイルサイズが異なる
                                fileChangedOrNew = true;
                            }
                        }
                        else
                        {
                            // 暗号化あり
                            // 宛先ディレクトリのメタデータにファイル情報が存在し、そのメタデータ情報におけるファイルサイズが元ファイルと同じであり、
                            // かつそのメタデータ情報に記載されている EncryptedPhysicalSize が宛先ディレクトリにある物理ファイルと全く同一である
                            // 場合は、宛先ファイルが正しく存在すると仮定する

                            string tmp1 = Fs.PathParser.GetFileName(destFilePath);
                            if ((destDirOldMetaData?.FileList.Where(x => x.EncrypedFileName._IsSamei(tmp1) && x.EncryptedPhysicalSize == destExistsMetadata.Size && x.MetaData.Size == srcFile.Size).Any() ?? false) == false)
                            {
                                // ファイルサイズが異なるとみなす
                                fileChangedOrNew = true;
                            }
                        }

                        // 日付を比較する。ただし宛先ディレクトリの物理的なファイルの日付は信用できないので、メタデータ上のファイルサイズと比較する
                        if (destDirOldMetaData != null)
                        {
                            DirSuperBackupMetadataFile?existsFileMetadataFromDirMetadata = destDirOldMetaData.FileList.Where(x => x.FileName._IsSamei(srcFile.Name)).SingleOrDefault();
                            if (existsFileMetadataFromDirMetadata == null)
                            {
                                // メタデータ上に存在しない
                                fileChangedOrNew = true;
                            }
                            else
                            {
                                if (existsFileMetadataFromDirMetadata.MetaData !.LastWriteTime !.Value.Ticks != srcFileMetadata.LastWriteTime !.Value.Ticks)
                                {
                                    // 最終更新日時が異なる
                                    fileChangedOrNew = true;
                                }
                            }
                        }
                        else
                        {
                            // 宛先ディレクトリ上にメタデータがない
                            fileChangedOrNew = true;
                        }
                    }
                    else
                    {
                        // 新しいファイルである
                        fileChangedOrNew = true;
                    }

                    string?oldFilePathToDelete = null;

                    if (fileChangedOrNew)
                    {
                        // ファイルが新しいか、または更新された場合は、そのファイルをバックアップする
                        // ただし、バックアップ先に同名のファイルがすでに存在する場合は、
                        // .old.xxxx.YYYYMMDD_HHMMSS.0123._backup_history のような形式でまだ存在しない連番に古いファイル名をリネームする

                        if (exists)
                        {
                            using (await SafeLock.LockWithAwait(cancel))
                            {
                                string yymmdd = Str.DateTimeToStrShort(DateTime.UtcNow);
                                string newOldFileName;

                                // 連番でかつ存在していないファイル名を決定する
                                for (int i = 0; ; i++)
                                {
                                    string newOldFileNameCandidate = $".old.{Fs.PathParser.GetFileName(destFilePath)}.{yymmdd}.{i:D4}{Consts.Extensions.DirSuperBackupHistory}";

                                    if (srcDirEnum.Where(x => x.Name._IsSamei(newOldFileNameCandidate)).Any() == false)
                                    {
                                        if (await Fs.IsFileExistsAsync(Fs.PathParser.Combine(destDir, newOldFileNameCandidate), cancel) == false)
                                        {
                                            newOldFileName = newOldFileNameCandidate;
                                            break;
                                        }
                                    }
                                }

                                // 変更されたファイル名を ._backup_history ファイルにリネーム実行する
                                string newOldFilePath = Fs.PathParser.Combine(destDir, newOldFileName);
                                await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("FileRename", destFilePath, newOldFilePath));
                                await Fs.MoveFileAsync(destFilePath, newOldFilePath, cancel);

                                oldFilePathToDelete = newOldFilePath;

                                // 隠しファイルにする
                                try
                                {
                                    var meta = await Fs.GetFileMetadataAsync(newOldFilePath, cancel: cancel);
                                    if (meta.Attributes != null && meta.Attributes.Bit(FileAttributes.Hidden) == false)
                                    {
                                        FileMetadata meta2 = new FileMetadata(attributes: meta.Attributes.BitAdd(FileAttributes.Hidden));

                                        await Fs.SetFileMetadataAsync(newOldFilePath, meta2, cancel);
                                    }
                                }
                                catch { }
                            }
                        }

                        // ファイルをコピーする
                        // 属性は、ファイルの日付情報のみコピーする
                        await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("FileCopy", srcFile.FullPath, destFilePath));

                        FileFlags flags = FileFlags.BackupMode | FileFlags.Async;

                        if (this.Options.Flags.Bit(DirSuperBackupFlags.BackupNoVerify) == false)
                        {
                            flags |= FileFlags.CopyFile_Verify;
                        }

                        await Fs.CopyFileAsync(srcFile.FullPath, destFilePath,
                                               new CopyFileParams(flags: flags, metadataCopier: new FileMetadataCopier(FileMetadataCopyMode.TimeAll),
                                                                  encryptOption: Options.EncryptPassword._IsNullOrZeroLen() ? EncryptOption.None : EncryptOption.Encrypt | EncryptOption.Compress,
                                                                  encryptPassword: Options.EncryptPassword, deleteFileIfVerifyFailed: true),
                                               cancel: cancel);

                        try
                        {
                            if (Options.EncryptPassword._IsNullOrZeroLen() == false)
                            {
                                var newFileMetadata = await Fs.GetFileMetadataAsync(destFilePath, FileMetadataGetFlags.NoPhysicalFileSize, cancel);

                                encryptedPhysicalSize = newFileMetadata.Size;
                            }
                        }
                        catch
                        {
                        }

                        if (Options.Flags.Bit(DirSuperBackupFlags.BackupMakeHistory) == false)
                        {
                            // History を残さない場合
                            // コピーに成功したので ._backup_history ファイルは削除する
                            if (oldFilePathToDelete._IsNotZeroLen())
                            {
                                try
                                {
                                    await Fs.DeleteFileAsync(oldFilePathToDelete, flags: FileFlags.BackupMode | FileFlags.ForceClearReadOnlyOrHiddenBitsOnNeed, cancel);
                                }
                                catch
                                {
                                }
                            }
                        }

                        Stat.Copy_NumFiles++;
                        Stat.Copy_TotalSize += srcFile.Size;
                    }
                    else
                    {
                        if (Options.EncryptPassword._IsNullOrZeroLen() == false)
                        {
                            string tmp1 = Fs.PathParser.GetFileName(destFilePath);

                            encryptedPhysicalSize = destDirOldMetaData?.FileList.Where(x => x.EncrypedFileName._IsSame(tmp1) && x.MetaData.Size == srcFile.Size).FirstOrDefault()?.EncryptedPhysicalSize;

                            if (encryptedPhysicalSize.HasValue == false)
                            {
                                encryptedPhysicalSize = destDirOldMetaData?.FileList.Where(x => x.EncrypedFileName._IsSamei(tmp1) && x.MetaData.Size == srcFile.Size).FirstOrDefault()?.EncryptedPhysicalSize;
                            }
                        }

                        Stat.Skip_NumFiles++;
                        Stat.Skip_TotalSize += srcFile.Size;

                        // ファイルの日付情報のみ更新する
                        try
                        {
                            await Fs.SetFileMetadataAsync(destFilePath, srcFileMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel);
                        }
                        catch
                        {
                            // ファイルの日付情報の更新は失敗してもよい
                        }
                    }
                }
                catch (Exception ex)
                {
                    Stat.Error_NumFiles++;
                    Stat.Error_TotalSize += srcFile.Size;

                    // ファイル単位のエラー発生
                    await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("FileError", srcFile.FullPath, destFilePath, ex.Message));

                    noError = false;
                }
                finally
                {
                    concurrentNum.Decrement();
                }

                // このファイルに関するメタデータを追加する
                if (srcFileMetadata != null)
                {
                    lock (destDirNewMetaData.FileList)
                    {
                        destDirNewMetaData.FileList.Add(new DirSuperBackupMetadataFile()
                        {
                            FileName              = srcFile.Name,
                            EncrypedFileName      = Options.EncryptPassword._IsNullOrZeroLen() ? null : srcFile.Name + Consts.Extensions.CompressedXtsAes256,
                            MetaData              = srcFileMetadata,
                            EncryptedPhysicalSize = encryptedPhysicalSize,
                        });
                    }
                }
            }, cancel : cancel);

            // 新しいメタデータをファイル名でソートする
            destDirNewMetaData.FileList = destDirNewMetaData.FileList.OrderBy(x => x.FileName, StrComparer.IgnoreCaseComparer).ToList();
            destDirNewMetaData.DirList  = destDirNewMetaData.DirList.OrderBy(x => x, StrComparer.IgnoreCaseComparer).ToList();

            // 新しいメタデータを書き込む
            string newMetadataFilePath = Fs.PathParser.Combine(destDir, $"{PrefixMetadata}{Str.DateTimeToStrShortWithMilliSecs(now.UtcDateTime)}{SuffixMetadata}");

            await Fs.WriteJsonToFileAsync(newMetadataFilePath, destDirNewMetaData, FileFlags.BackupMode | FileFlags.OnCreateSetCompressionFlag, cancel : cancel);
        }
        catch (Exception ex)
        {
            Stat.Error_Dir++;

            noError = false;

            // ディレクトリ単位のエラー発生
            await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirError1", srcDir, destDir, ex.Message));
        }

        // 再度 宛先ディレクトリの日付情報のみ属性書き込みする (Linux の場合、中のファイルを更新するとディレクトリの日時が変ってしまうため)
        try
        {
            if (srcDirMetadata != null)
            {
                await Fs.SetFileMetadataAsync(destDir, srcDirMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel);
            }
        }
        catch
        {
            // 属性書き込みは失敗してもよい
        }

        if (srcDirEnum != null)
        {
            bool ok = false;

            try
            {
                // ソースディレクトリの列挙に成功した場合は、サブディレクトリに対して再帰的に実行する
                foreach (var subDir in srcDirEnum.Where(x => x.IsDirectory && x.IsCurrentOrParentDirectory == false))
                {
                    // シンボリックリンクは無視する
                    if (subDir.IsSymbolicLink == false)
                    {
                        // 無視リストのいずれにも合致しない場合のみ
                        if (ignoreDirNamesList.Where(x => x._IsSamei(subDir.Name)).Any() == false)
                        {
                            await DoSingleDirBackupAsync(Fs.PathParser.Combine(srcDir, subDir.Name), Fs.PathParser.Combine(destDir, subDir.Name), cancel, ignoreDirNames);
                        }
                    }
                }

                ok = true;
            }
            catch (Exception ex)
            {
                // 何らかのディレクトリ単位のエラーで catch されていないものが発生
                Stat.Error_Dir++;

                // ディレクトリ単位のエラー発生
                await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirError2", srcDir, destDir, ex.Message));
            }

            if (ok)
            {
                if (noError)
                {
                    // ここまでの処理で何も問題がなければ (このディレクトリ内のすべてのファイルのコピーやメタデータの更新に成功しているなであれば)
                    // Sync オプションが付与されている場合、不要なサブディレクトリとファイルを削除する

                    if (this.Options.Flags.Bit(DirSuperBackupFlags.BackupSync))
                    {
                        try
                        {
                            // 両方のディレクトリを再列挙いたします
                            var srcDirEnum2  = (await Fs.EnumDirectoryAsync(srcDir, false, EnumDirectoryFlags.NoGetPhysicalSize, cancel)).OrderBy(x => x.Name, StrComparer.IgnoreCaseComparer).ToArray();
                            var destDirEnum2 = (await Fs.EnumDirectoryAsync(destDir, false, EnumDirectoryFlags.NoGetPhysicalSize, cancel)).OrderBy(x => x.Name, StrComparer.IgnoreCaseComparer).ToArray();

                            // 余分なファイルを削除いたします
                            var extraFiles = destDirEnum2.Where(x => x.IsFile && x.IsSymbolicLink == false)
                                             .Where(x => x.Name._StartWithi(DirSuperBackup.PrefixMetadata) == false && x.Name._EndsWithi(DirSuperBackup.SuffixMetadata) == false)
                                             .Where(x => srcDirEnum2.Where(y => y.IsFile && y.Name._IsSameiTrim(x.Name)).Any() == false)
                                             .Where(x => srcDirEnum2.Where(y => y.IsFile && (y.Name + Consts.Extensions.CompressedXtsAes256)._IsSameiTrim(x.Name)).Any() == false);

                            foreach (var extraFile in extraFiles)
                            {
                                string fullPath = Fs.PathParser.Combine(destDir, extraFile.Name);

                                await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("DirSyncDeleteFile", fullPath));

                                try
                                {
                                    await Fs.DeleteFileAsync(fullPath, FileFlags.BackupMode | FileFlags.ForceClearReadOnlyOrHiddenBitsOnNeed, cancel);

                                    Stat.SyncDelete_NumFiles++;
                                }
                                catch (Exception ex)
                                {
                                    Stat.Error_NumDeleteFiles++;
                                    await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirSyncDeleteFileError", fullPath, ex.Message));
                                }
                            }

                            // 余分なサブディレクトリを削除いたします
                            var extraSubDirs = destDirEnum2.Where(x => x.IsDirectory && x.IsCurrentOrParentDirectory == false && x.IsSymbolicLink == false)
                                               .Where(x => srcDirEnum2.Where(y => y.IsDirectory && y.IsCurrentOrParentDirectory == false && y.Name._IsSameiTrim(x.Name)).Any() == false);

                            foreach (var extraSubDir in extraSubDirs)
                            {
                                string fullPath = Fs.PathParser.Combine(destDir, extraSubDir.Name);

                                await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("DirSyncDeleteSubDir", fullPath));

                                try
                                {
                                    await Fs.DeleteDirectoryAsync(fullPath, true, cancel);

                                    Stat.SyncDelete_NumDirs++;
                                }
                                catch (Exception ex)
                                {
                                    Stat.Error_NumDeleteDirs++;
                                    await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirSyncDeleteSubDirError", fullPath, ex.Message));
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            // 何らかのディレクトリ単位のエラーで catch されていないものが発生
                            Stat.Error_Dir++;

                            // ディレクトリ単位のエラー発生
                            await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirSyncEnumError", srcDir, destDir, ex.Message));
                        }
                    }
                }
            }
        }


        // 再度 宛先ディレクトリの日付情報のみ属性書き込みする (Linux の場合、中のファイルを更新するとディレクトリの日時が変ってしまうため)
        try
        {
            if (srcDirMetadata != null)
            {
                await Fs.SetFileMetadataAsync(destDir, srcDirMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel);
            }
        }
        catch
        {
            // 属性書き込みは失敗してもよい
        }
    }
예제 #8
0
        static int ReleaseUnix(ConsoleService c, string cmdName, string str)
        {
            ConsoleParam[] args =
            {
                new ConsoleParam("[id]"),
                new ConsoleParam("IGNOREERROR"),
                new     ConsoleParam("DEBUG"),
                new ConsoleParam("SERIAL"),
            };
            ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);

            int      version, build;
            string   name;
            DateTime date;

            Win32BuildUtil.ReadBuildInfoFromTextFile(out build, out version, out name, out date);
            BuildSoftware[] softs  = BuildSoftwareList.List;
            bool            serial = vl["SERIAL"].BoolValue;

            if (Str.IsEmptyStr(vl.DefaultParam.StrValue))
            {
                Con.WriteLine("IDs:");
                foreach (BuildSoftware soft in softs)
                {
                    if (soft.Os.IsWindows == false)
                    {
                        soft.SetBuildNumberVersionName(build, version, name, date);
                        Con.WriteLine("  {0}", soft.IDString);
                        Con.WriteLine("    - \"{0}\"", soft.OutputFileName);
                    }
                }
            }
            else
            {
                string key = vl.DefaultParam.StrValue;
                bool   all = false;

                if ("all".StartsWith(key, StringComparison.InvariantCultureIgnoreCase))
                {
                    all = true;
                }

                if ("clean".StartsWith(key, StringComparison.InvariantCultureIgnoreCase))
                {
                    // Delete the release directory
                    Paths.DeleteAllReleaseTarGz();
                    Con.WriteLine("Clean completed.");
                    return(0);
                }

                List <BuildSoftware> o = new List <BuildSoftware>();

                foreach (BuildSoftware soft in softs)
                {
                    soft.SetBuildNumberVersionName(build, version, name, date);

                    if (soft.Os.IsWindows == false)
                    {
                        if (all || soft.IDString.IndexOf(key, StringComparison.InvariantCultureIgnoreCase) != -1)
                        {
                            o.Add(soft);
                        }
                    }
                }

                if (o.Count == 0)
                {
                    throw new ApplicationException(string.Format("Software ID '{0}' not found.", key));
                }
                else
                {
                    if (all)
                    {
                        // Delete the release directory
                        Paths.DeleteAllReleaseTarGz();
                    }
                    else
                    {
                        IO.MakeDir(Paths.ReleaseDir);
                    }

                    if (serial)
                    {
                        // Build in series
                        int i;
                        for (i = 0; i < o.Count; i++)
                        {
                            Con.WriteLine("{0} / {1}: Executing for '{2}'...",
                                          i + 1, o.Count, o[i].IDString);

                            BuildHelper.BuildMain(o[i], vl["DEBUG"].BoolValue);
                        }
                    }
                    else if (o.Count == 1)
                    {
                        // To build
                        BuildHelper.BuildMain(o[0], vl["DEBUG"].BoolValue);
                    }
                    else
                    {
                        // Make a child process build
                        Process[] procs = new Process[o.Count];

                        int i;

                        for (i = 0; i < o.Count; i++)
                        {
                            Con.WriteLine("{0} / {1}: Executing for '{2}'...",
                                          i + 1, o.Count, o[i].IDString);

                            procs[i] = Kernel.Run(Env.ExeFileName,
                                                  string.Format("/PAUSEIFERROR:{1} /DT:{2} /CMD:ReleaseUnix /DEBUG:{3} {0}",
                                                                o[i].IDString, vl["IGNOREERROR"].BoolValue ? "no" : "yes", Str.DateTimeToStrShort(BuildSoftwareList.ListCreatedDateTime), vl["DEBUG"].BoolValue ? "yes" : "no")
                                                  );
                        }

                        Con.WriteLine("Waiting child processes...");

                        int numError = 0;

                        for (i = 0; i < o.Count; i++)
                        {
                            procs[i].WaitForExit();

                            bool ok = procs[i].ExitCode == 0;

                            if (ok == false)
                            {
                                numError++;
                            }

                            Con.WriteLine("{0} / {1} ({2}):", i + 1, o.Count, o[i].IDString);
                            Con.WriteLine("       {0}", ok ? "Success" : "* Error *");
                        }

                        Con.WriteLine();
                        if (numError != 0)
                        {
                            throw new ApplicationException(string.Format("{0} Errors.", numError));
                        }
                        Con.WriteLine("No Errors.");
                    }
                }
            }

            return(0);
        }