Ejemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="remote">Remote host to download from</param>
        /// <param name="localXpath">Local directory for remote include directories, e.g. D:\Project1\remote\192.168.0.1.</param>
        public void RebaseToLocal(RemoteHost remote, AbsoluteCrosspath localXpath)
        {
            if (this.Flavor == CrosspathFlavor.Windows)
            {
                return;
            }

            int xtractBufSize = 65536;

            Byte[] zipExtractBuf = new Byte[xtractBufSize];

            String remoteFilename        = $"/tmp/{ShortName}.zip";
            String localDirectoryPattern = $@"include\{ShortName}";
            String localFilenamePattern  = $"{ShortName}.zip";

            AbsoluteCrosspath xLocalIncludeDirectory = localXpath.Appended(RelativeCrosspath.FromString(localDirectoryPattern));
            String            localIncludeDirectory  = xLocalIncludeDirectory.ToString();
            String            localFilename          = localXpath.Appended(RelativeCrosspath.FromString(localFilenamePattern)).ToString();

            Logger.WriteLine(LogLevel.Info, $"Rolling {this} into {localFilenamePattern}...");
            Directory.CreateDirectory(localIncludeDirectory);
            if (remote.Execute($"pushd {this} && zip -1 -r -q {remoteFilename} . && popd", out String result) != RemoteHost.Success)
            {
                Logger.WriteLine(LogLevel.Error, result);
                // FIXME, hack
                this.Rebase(this, xLocalIncludeDirectory);
                autoDownloaded = true;
                return;
            }

            remote.DownloadFile(remoteFilename, localFilename);
            File.WriteAllText(xLocalIncludeDirectory.Appended(RelativeCrosspath.FromString($@"..\{ShortName}_origin.txt")).ToString(), this.ToString());

            // not working bcz of NTFS case & special names restrictions. extract manually.
            //ZipFile.ExtractToDirectory(localFilename, localDirectory, Encoding.UTF8);

            using (FileStream fs = new FileStream(localFilename, FileMode.Open)) {
                ZipArchive za = new ZipArchive(fs, ZipArchiveMode.Read);
                foreach (ZipArchiveEntry zaEntry in za.Entries)
                {
                    RelativeCrosspath xRelPath = RelativeCrosspath.FromString(zaEntry.FullName);
                    AbsoluteCrosspath xPath    = xLocalIncludeDirectory.Appended(xRelPath);
                    if (zaEntry.FullName.EndsWith("/"))
                    {
                        // packed directory
                        continue;
                    }

                    String path = xPath.ToString();
                    if (File.Exists(path))
                    {
                        Logger.WriteLine(LogLevel.Warning, $"file '{zaEntry.FullName}' already exists as '{path}' - case problems?");
                        continue;
                    }

                    // hax, remove leading / from path
                    if (xRelPath.ToString() == Compiler.RemoteTempFile.Substring(1))
                    {
                        continue;
                    }

                    String dirname = new AbsoluteCrosspath(xPath).ToContainingDirectory().ToString();
                    try {
                        Directory.CreateDirectory(dirname);
                        // packed file
                        using (FileStream xfs = new FileStream(path, FileMode.CreateNew)) {
                            using (Stream zas = zaEntry.Open()) {
                                while (true)
                                {
                                    int len = zas.Read(zipExtractBuf, 0, xtractBufSize);
                                    if (len == 0)
                                    {
                                        // EOF
                                        break;
                                    }

                                    xfs.Write(zipExtractBuf, 0, len);
                                }
                                zas.Close();
                            }
                        }
                    }
                    catch (Exception e) {
                        Logger.WriteLine(LogLevel.Error, $"Could not extract '${zaEntry.FullName}': ${e.Message}");
                    }
                }
            }

            // if extraction went ok, we can remove files
            remote.Execute($"rm {remoteFilename}", out String _);
            File.Delete(localFilename);

            // since we definitely have a local copy of include directory, rebase on it
            this.Rebase(this, xLocalIncludeDirectory);
            autoDownloaded = true;
        }