Ejemplo n.º 1
0
        /// <summary>
        /// Extract the files given RelativePathInPack
        /// </summary>
        /// <param name="files"></param>
        public void ExtractFiles(List <string> files)
        {
            _prolibExe.StartInfo.WorkingDirectory = _plExtractionFolder;

            // create the subfolders needed to extract each file
            foreach (var folder in files.Select(Path.GetDirectoryName).Distinct(StringComparer.CurrentCultureIgnoreCase))
            {
                try {
                    Directory.CreateDirectory(Path.Combine(_plExtractionFolder, folder));
                } catch (Exception e) {
                    ErrorHandler.LogError(e);
                }
            }

            // for files containing a space, we don't have a choice, call delete for each...
            foreach (var file in files.Where(deploy => deploy.ContainsFast(" ")))
            {
                _prolibExe.Arguments = _archivePath.Quoter() + " -extract " + file.Quoter();
                if (!_prolibExe.TryDoWait(true))
                {
                    ErrorHandler.LogError(new Exception(_prolibExe.ErrorOutput.ToString()), "Erreur durant l'extraction de fichiers depuis une .pl");
                }
            }

            var remainingFiles = files.Where(deploy => !deploy.ContainsFast(" ")).ToList();

            if (remainingFiles.Count > 0)
            {
                // for the other files, we can use the -pf parameter
                var pfContent = new StringBuilder();
                pfContent.AppendLine("-extract");
                foreach (var file in remainingFiles)
                {
                    pfContent.AppendLine(file);
                }

                var pfPath = _plExtractionFolder + Path.GetFileName(_archivePath) + "~" + Path.GetRandomFileName() + ".pf";

                try {
                    File.WriteAllText(pfPath, pfContent.ToString(), Encoding.Default);
                } catch (Exception e) {
                    ErrorHandler.LogError(e);
                }

                _prolibExe.Arguments = _archivePath.Quoter() + " -pf " + pfPath.Quoter();
                if (!_prolibExe.TryDoWait(true))
                {
                    ErrorHandler.LogError(new Exception(_prolibExe.ErrorOutput.ToString()), "Erreur durant l'extraction de fichiers depuis une .pl");
                }

                try {
                    if (File.Exists(pfPath))
                    {
                        File.Delete(pfPath);
                    }
                } catch (Exception e) {
                    ErrorHandler.LogError(e);
                }
            }
        }
Ejemplo n.º 2
0
        public void PackFileSet(IDictionary <string, FileToDeployInPack> files, CompressionLevel compLevel, EventHandler <ArchiveProgressEventArgs> progressHandler)
        {
            var archiveFolder = Path.GetDirectoryName(_archivePath);

            if (!string.IsNullOrEmpty(archiveFolder))
            {
                _prolibExe.StartInfo.WorkingDirectory = archiveFolder;
            }

            // for files containing a space, we don't have a choice, call delete for each...
            foreach (var file in files.Values.Where(deploy => deploy.RelativePathInPack.ContainsFast(" ")))
            {
                _prolibExe.Arguments = _archivePath.ProQuoter() + " -delete " + file.RelativePathInPack.ProQuoter();
                var isOk = _prolibExe.TryDoWait(true);
                if (progressHandler != null)
                {
                    progressHandler(this, new ArchiveProgressEventArgs(ArchiveProgressType.FinishFile, file.RelativePathInPack, isOk ? null : new Exception(_prolibExe.ErrorOutput.ToString())));
                }
            }

            var remainingFiles = files.Values.Where(deploy => !deploy.RelativePathInPack.ContainsFast(" ")).ToList();

            if (remainingFiles.Count > 0)
            {
                // for the other files, we can use the -pf parameter
                var pfContent = new StringBuilder();
                pfContent.AppendLine("-delete");
                foreach (var file in remainingFiles)
                {
                    pfContent.AppendLine(file.RelativePathInPack);
                }

                Exception ex     = null;
                var       pfPath = _archivePath + "~" + Path.GetRandomFileName() + ".pf";

                try {
                    File.WriteAllText(pfPath, pfContent.ToString(), Encoding.Default);
                } catch (Exception e) {
                    ex = e;
                }

                _prolibExe.Arguments = _archivePath.ProQuoter() + " -pf " + pfPath.ProQuoter();
                var isOk = _prolibExe.TryDoWait(true);

                try {
                    if (ex == null)
                    {
                        File.Delete(pfPath);
                    }
                } catch (Exception e) {
                    ex = e;
                }

                if (progressHandler != null)
                {
                    foreach (var file in files.Values.Where(deploy => !deploy.RelativePathInPack.ContainsFast(" ")))
                    {
                        progressHandler(this, new ArchiveProgressEventArgs(ArchiveProgressType.FinishFile, file.RelativePathInPack, ex ?? (isOk ? null : new Exception(_prolibExe.ErrorOutput.ToString()))));
                    }
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Deploy a given list of files (can reduce the list if there are duplicated items so it returns it)
        /// </summary>
        public List <FileToDeploy> DeployFiles(List <FileToDeploy> deployToDo, Action <float> updateDeploymentPercentage = null)
        {
            int[] totalFile   = { 0 };
            int[] nbFilesDone = { 0 };

            // make sure to transfer a given file only once at the same place (happens with .cls file since a source
            // can have several .r files generated if it is used in another classes)
            deployToDo = deployToDo
                         .GroupBy(deploy => deploy.To)
                         .Select(group => group.FirstOrDefault(move => Path.GetFileNameWithoutExtension(move.From ?? "").Equals(Path.GetFileNameWithoutExtension(move.Origin))) ?? group.First())
                         .ToList();

            totalFile[0] = deployToDo.Count;

            // check that every target dir exist (for copy/move deployments)
            deployToDo
            .Where(deploy => deploy.DeployType == DeployType.Copy || deploy.DeployType == DeployType.Move)
            .GroupBy(deploy => Path.GetDirectoryName(deploy.To))
            .Select(group => group.First())
            .ToNonNullList()
            .ForEach(deploy => Utils.CreateDirectory(Path.GetDirectoryName(deploy.To)));

            #region for archives (zip/pl)

            // for archives, compute the path to the archive file (+ make sure the directory of the archive exists)
            deployToDo.Where(deploy => deploy.DeployType <= DeployType.Archive).ToNonNullList().ForEach(deploy => {
                var ext = deploy.DeployType == DeployType.Prolib ? ".pl" : ".zip";
                var pos = deploy.To.LastIndexOf(ext, StringComparison.CurrentCultureIgnoreCase);
                if (pos >= 0)
                {
                    var posEnd                   = pos + ext.Length;
                    deploy.ArchivePath           = deploy.To.Substring(0, posEnd);
                    deploy.RelativePathInArchive = deploy.To.Substring(posEnd + 1);

                    // ensure that the folder to the .archive file exists
                    Utils.CreateDirectory(Path.GetDirectoryName(deploy.ArchivePath));

                    // for .zip, open the zip stream for later usage
                    if (deploy.DeployType > DeployType.Prolib)
                    {
                        if (!_openedZip.ContainsKey(deploy.ArchivePath))
                        {
                            try {
                                if (!File.Exists(deploy.ArchivePath))
                                {
                                    _openedZip.Add(deploy.ArchivePath, ZipStorer.Create(deploy.ArchivePath, "Created with 3P @ " + DateTime.Now + "\r\n" + Config.UrlWebSite));
                                }
                                else
                                {
                                    _openedZip.Add(deploy.ArchivePath, ZipStorer.Open(deploy.ArchivePath, FileAccess.Write));
                                    _filesToRemoveFromZip.Add(deploy.ArchivePath, new HashSet <string>());
                                }
                            } catch (Exception e) {
                                ErrorHandler.ShowErrors(e, "Couldn't create/open the .zip file");
                            }
                        }

                        // we didn't create the zip? then we need to remove this file if it exists
                        if (_filesToRemoveFromZip.ContainsKey(deploy.ArchivePath))
                        {
                            _filesToRemoveFromZip[deploy.ArchivePath].Add(deploy.RelativePathInArchive.Replace('\\', '/'));
                        }
                    }
                }
            });

            #endregion

            #region for .pl deployments, we treat them before anything else

            // for PL, we need to MOVE each file into a temporary folder with the internal structure of the .pl file,
            // then move it back where it was for further deploys...

            var plDeployments = deployToDo
                                .Where(deploy => deploy.DeployType == DeployType.Prolib)
                                .ToNonNullList();

            if (plDeployments.Count > 0)
            {
                // then we create a unique temporary folder for each .pl
                var dicPlToTempFolder = new Dictionary <string, string>(StringComparer.CurrentCultureIgnoreCase);
                foreach (var pathPl in plDeployments.Where(deploy => !string.IsNullOrEmpty(deploy.ArchivePath)).Select(deploy => deploy.ArchivePath).Distinct())
                {
                    // create a unique temp folder for this .pl
                    if (!dicPlToTempFolder.ContainsKey(pathPl))
                    {
                        var plDirPath = Path.GetDirectoryName(pathPl);
                        if (plDirPath != null)
                        {
                            var uniqueTempFolder = Path.Combine(plDirPath, Path.GetFileName(pathPl) + "~" + Path.GetRandomFileName());
                            dicPlToTempFolder.Add(pathPl, uniqueTempFolder);
                            Utils.CreateDirectory(uniqueTempFolder, FileAttributes.Hidden);
                        }
                    }
                }

                var prolibMessage = new StringBuilder();

                // for each .pl that needs to be created...
                foreach (var pl in dicPlToTempFolder)
                {
                    var pl1 = pl;
                    var onePlDeployments = plDeployments
                                           .Where(deploy => !string.IsNullOrEmpty(deploy.ArchivePath) && deploy.ArchivePath.Equals(pl1.Key))
                                           .ToNonNullList();
                    if (onePlDeployments.Count == 0)
                    {
                        continue;
                    }

                    //  we set the temporary folder on which each file will be copied..
                    // Tuple : <(base) temp directory, relative path in pl, path to .pl>
                    var dicTempFolderToPl = new Dictionary <string, Tuple <string, string, string> >(StringComparer.CurrentCultureIgnoreCase);
                    foreach (var fileToDeploy in onePlDeployments)
                    {
                        if (string.IsNullOrEmpty(fileToDeploy.ArchivePath))
                        {
                            continue;
                        }

                        if (dicPlToTempFolder.ContainsKey(fileToDeploy.ArchivePath))
                        {
                            fileToDeploy.ToTemp = Path.Combine(
                                dicPlToTempFolder[fileToDeploy.ArchivePath],
                                fileToDeploy.To.Replace(fileToDeploy.ArchivePath, "").TrimStart('\\')
                                );

                            // If not already done, remember that the *.r code in this temp folder must be integrated to this .pl file
                            var tempSubFolder = Path.GetDirectoryName(fileToDeploy.ToTemp);
                            if (!string.IsNullOrEmpty(tempSubFolder) && !dicTempFolderToPl.ContainsKey(tempSubFolder))
                            {
                                dicTempFolderToPl.Add(
                                    tempSubFolder,
                                    new Tuple <string, string, string>(
                                        dicPlToTempFolder[fileToDeploy.ArchivePath],                                                  // path of the temp dir
                                        Path.GetDirectoryName(fileToDeploy.To.Replace(fileToDeploy.ArchivePath, "").TrimStart('\\')), // relative path in .pl
                                        fileToDeploy.ArchivePath)                                                                     // path to the .pl file
                                    );

                                // also, create the folder
                                Utils.CreateDirectory(tempSubFolder);
                            }
                        }
                    }

                    var prolibExe = new ProcessIo(ProEnv.ProlibPath);

                    // for each subfolder in the .pl
                    foreach (var plSubFolder in dicTempFolderToPl)
                    {
                        var onePlSubFolderDeployments = onePlDeployments
                                                        .Where(deploy => plSubFolder.Key.Equals(Path.GetDirectoryName(deploy.ToTemp)))
                                                        .ToNonNullList();
                        if (onePlSubFolderDeployments.Count == 0)
                        {
                            continue;
                        }

                        Parallel.ForEach(onePlSubFolderDeployments, deploy => {
                            if (File.Exists(deploy.From))
                            {
                                deploy.IsOk = !string.IsNullOrEmpty(deploy.ToTemp) && Utils.MoveFile(deploy.From, deploy.ToTemp);
                            }
                            if (deploy.IsOk)
                            {
                                nbFilesDone[0]++;
                            }
                            if (updateDeploymentPercentage != null)
                            {
                                updateDeploymentPercentage((float)nbFilesDone[0] / totalFile[0] * 100);
                            }
                        });

                        // now we just need to add the content of temp folders into the .pl
                        prolibExe.StartInfo.WorkingDirectory = plSubFolder.Value.Item1; // base temp dir
                        prolibExe.Arguments = plSubFolder.Value.Item3.ProQuoter() + " -create -nowarn -add " + Path.Combine(plSubFolder.Value.Item2, "*").ProQuoter();
                        if (!prolibExe.TryDoWait(true))
                        {
                            prolibMessage.Append(prolibExe.ErrorOutput);
                        }

                        Parallel.ForEach(onePlSubFolderDeployments, deploy => {
                            deploy.IsOk = deploy.IsOk && Utils.MoveFile(deploy.ToTemp, deploy.From);
                        });
                    }

                    // compress .pl
                    prolibExe.StartInfo.WorkingDirectory = Path.GetDirectoryName(pl.Key) ?? "";
                    prolibExe.Arguments = pl.Key.ProQuoter() + " -compress -nowarn";
                    if (!prolibExe.TryDoWait(true))
                    {
                        prolibMessage.Append(prolibExe.ErrorOutput);
                    }

                    // delete temp folders
                    Utils.DeleteDirectory(pl.Value, true);
                }

                if (prolibMessage.Length > 0)
                {
                    UserCommunication.Notify("Errors occured when trying to create/add files to the .pl file :<br>" + prolibMessage, MessageImg.MsgError, "Prolib output", "Errors");
                }
            }

            #endregion

            #region for zip

            // remove the files that are already in the zip file or they will appear twice when we add them
            foreach (var kpv in _filesToRemoveFromZip)
            {
                ZipStorer zip           = _openedZip[kpv.Key];
                var       filesToDelete = zip.ReadCentralDir().Where(zipFileEntry => kpv.Value.Contains(zipFileEntry.FilenameInZip)).ToList();
                _openedZip.Remove(kpv.Key);
                ZipStorer.RemoveEntries(ref zip, filesToDelete);
                _openedZip.Add(kpv.Key, zip);
            }

            #endregion


            // do a deployment action for each file (parallel for MOVE and COPY)
            Parallel.ForEach(deployToDo.Where(deploy => deploy.DeployType >= DeployType.Copy), file => {
                if (DeploySingleFile(file))
                {
                    nbFilesDone[0]++;
                }
                if (updateDeploymentPercentage != null)
                {
                    updateDeploymentPercentage((float)nbFilesDone[0] / totalFile[0] * 100);
                }
            });
            // don't use parallel for the other types
            foreach (var file in deployToDo.Where(deploy => deploy.DeployType < DeployType.Copy))
            {
                if (DeploySingleFile(file))
                {
                    nbFilesDone[0]++;
                }
                if (updateDeploymentPercentage != null)
                {
                    updateDeploymentPercentage((float)nbFilesDone[0] / totalFile[0] * 100);
                }
            }

            #region for zip, dispose of zipStorers

            // also, need to dispose of the object/stream here
            foreach (var zipStorer in _openedZip)
            {
                zipStorer.Value.Close();
            }
            _openedZip.Clear();

            #endregion

            return(deployToDo);
        }