// Called from the worker thread
 public void HandleFileRemoved(object sender, UpdateFileStatus status)
 {
     parentForm.AsyncInvokeScript(new ScriptCall(FileRemovedMethod, new object[] { status.file, status.length }));
 }
 private static void HandleFileFetchStarted(object sender, UpdateFileStatus msg)
 {
     Console.WriteLine("Downloading File: " + msg.file + " ...");
 }
 private static void HandleFileRemoved(object sender, UpdateFileStatus msg)
 {
     Console.WriteLine("Removed file: " + msg.file);
 }
        /// <summary>
        ///   Examine the local manifest and the remote manifest, and build
        ///   a concept of what files need to be added/removed/modified.
        /// </summary>
        public void ProcessManifest(FileFetcher fetcher)
        {
            string baseDir = baseDirectory;
            string currentManifestFile = Path.Combine(baseDir, CurrentManifest);
            string newManifestFile = Path.Combine(baseDir, NewManifest);

            ReadManifest(currentManifestDict, currentIgnorePatterns, currentExcludePatterns, currentManifestFile);

            OnStateChanged(UpdateState.FetchingManifest);
            fetcher.FetchFile(NewManifest, sourceUrl, baseDir, null);

            ReadManifest(targetManifestDict, targetIgnorePatterns, targetExcludePatterns, newManifestFile);

            fetcher.ProgressUpdate += fetcher_ProgressUpdate;
            bytesNeeded = 0;
            filesNeeded = 0;

            List<string> newFiles = new List<string>();
            List<string> removedFiles = new List<string>();
            List<string> modifiedFiles = new List<string>();
            foreach (string key in targetManifestDict.Keys) {
                ManifestEntry targetEntry = targetManifestDict[key];
                if (targetEntry.type == "dir") {
                    if (IsIgnored(targetIgnorePatterns, targetEntry.name))
                        Debug.Assert(false, "Ignoring directory: " + targetEntry.name);
                }
                // if the entry is ignored, just skip it
                if (IsIgnored(targetIgnorePatterns, targetEntry.name))
                    continue;
                if (targetEntry.type == "dir") {
                    MakeDirectory(targetEntry.name);
                    if (!currentManifestDict.ContainsKey(key)) {
                        UpdateFileStatus ufs = new UpdateFileStatus();
                        ufs.file = targetEntry.name;
                        ufs.length = 0;
                        OnFileAdded(ufs);
                    }
                    continue;
                }
                if (!currentManifestDict.ContainsKey(key)) {
                    newFiles.Add(key);
                    bytesNeeded += targetEntry.length;
                    filesNeeded++;
                } else {
                    ManifestEntry currentEntry = currentManifestDict[key];
                    Debug.Assert(currentEntry.digest != null);
                    Debug.Assert(targetEntry.digest != null);
                    Debug.Assert(currentEntry.digest.Length == targetEntry.digest.Length);
                    bool matches = true;
                    for (int i = 0; i < currentEntry.digest.Length; ++i) {
                        if (currentEntry.digest[i] != targetEntry.digest[i]) {
                            matches = false;
                            break;
                        }
                    }
                    if (!matches) {
                        modifiedFiles.Add(key);
                        bytesNeeded += targetEntry.length;
                        filesNeeded++;
                    }
                }
            }
            foreach (string key in currentManifestDict.Keys) {
                if (IsIgnored(targetIgnorePatterns, key)) {
                    UpdateFileStatus ufs = new UpdateFileStatus();
                    ufs.file = key;
                    OnFileIgnored(ufs);
                    continue;
                }
                // TODO: this should be cleaned up to prevent me from
                // removing entries managed by another repository
                if (!targetManifestDict.ContainsKey(key))
                    removedFiles.Add(key);
            }

            // At this point, we are about to start fetching new files,
            // so remove our existing manifest.  This will cause us to
            // do a full scan if our download is interrupted, which will
            // be more efficient than fetching everything again.
            File.Delete(currentManifestFile);

            UpdaterStatus updateStatus = new UpdaterStatus();
            updateStatus.files = filesNeeded;
            updateStatus.filesFetched = 0;
            updateStatus.bytes = bytesNeeded;
            updateStatus.bytesFetched = 0;
            updateStatus.bytesTransferred = 0;
            OnUpdateStarted(updateStatus);
            OnStateChanged(UpdateState.UpdatingFiles);

            // Sort and reverse the removed files so that subdirectory entries are listed
            // before their parent directories.
            removedFiles.Sort();
            removedFiles.Reverse();
            foreach (string file in removedFiles) {
                UpdateFileStatus ufs = new UpdateFileStatus();
                ufs.file = file;
                string fname = Path.Combine(baseDir, file);
                if (Directory.Exists(fname))
                    Directory.Delete(fname);
                else if (File.Exists(fname))
                    File.Delete(fname);
                else
                    Debug.Assert(false, "Unexpected removal of entry: " + fname + string.Format(" - '{0}' + '{1}'", baseDir, file));
                OnFileRemoved(ufs);
            }
            // Handle modified files
            foreach (string file in modifiedFiles) {
                long lastBytesUpdated = bytesUpdated;
                UpdateFileStatus ufs = new UpdateFileStatus();
                ufs.file = file;
                ufs.length = targetManifestDict[file].length;
                OnFileFetchStarted(ufs);
                // Trace.TraceInformation("Fetching modified file: {0}", file);
                // Trace.TraceInformation("Old Digest: {0}", currentManifestDict[file].DigestString);
                // Trace.TraceInformation("New Digest: {0}", targetManifestDict[file].DigestString);
                long length, compressedLength;
                if (!fetcher.FetchFile(file, sourceUrl, baseDir, targetManifestDict[file].digest,
                                       out length, out compressedLength))
                    throw new Exception(string.Format("Unable to retrieve valid file: '{0}'", file));
                if (length != ufs.length) {
                    string msg = string.Format("Unable to retrieve valid file: '{0}' - size mismatch (got {1} but expected {2})",
                                               file, length, ufs.length);
                    throw new Exception(msg);
                }
                ufs.compressedLength = compressedLength;
                OnFileFetchEnded(ufs);
                OnFileModified(ufs);
                filesUpdated++;
                bytesUpdated = lastBytesUpdated + ufs.length;
            }
            // Handle new files
            foreach (string file in newFiles) {
                long lastBytesUpdated = bytesUpdated;
                UpdateFileStatus ufs = new UpdateFileStatus();
                ufs.file = file;
                ufs.length = targetManifestDict[file].length;
                OnFileFetchStarted(ufs);
                // Trace.TraceInformation("Fetching new file: {0}", file);
                long length, compressedLength;
                if (!fetcher.FetchFile(file, sourceUrl, baseDir, targetManifestDict[file].digest,
                                       out length, out compressedLength))
                    throw new Exception(string.Format("Unable to retrieve valid file: '{0}'", file));
                if (length != ufs.length) {
                    string msg = string.Format("Unable to retrieve valid file: '{0}' - size mismatch (got {1} but expected {2})",
                                               file, length, ufs.length);
                    throw new Exception(msg);
                }
                ufs.compressedLength = compressedLength;
                OnFileFetchEnded(ufs);
                OnFileAdded(ufs);
                filesUpdated++;
                bytesUpdated = lastBytesUpdated + ufs.length;
            }

            File.Copy(newManifestFile, currentManifestFile);

            updateStatus.filesFetched = filesUpdated;
            updateStatus.bytesFetched = fetcher.BytesFetched;
            updateStatus.bytesTransferred = fetcher.BytesTransferred;

            OnUpdateCompleted(updateStatus);
            OnStateChanged(UpdateState.UpdateEnded);
        }
 private static void HandleFileFetchEnded(object sender, UpdateFileStatus msg)
 {
     Console.WriteLine("Downloaded File: " + msg.file);
 }
 private void LogFileRemoved(object sender, UpdateFileStatus msg)
 {
     if (log != null)
         log.WriteLine("Removed file: " + msg.file);
 }
 private void LogFileFetchStarted(object sender, UpdateFileStatus msg)
 {
     if (log != null)
         log.WriteLine("Downloading File: " + msg.file + " ...");
 }
 private void LogFileFetchEnded(object sender, UpdateFileStatus msg)
 {
     if (log != null)
         log.WriteLine("Downloaded File: {0} ({1}/{2} bytes)", msg.file, msg.compressedLength, msg.length);
 }
 protected void OnFileRemoved(UpdateFileStatus status)
 {
     if (FileRemoved != null)
         FileRemoved(this, status);
 }
 protected void OnFileFetchStarted(UpdateFileStatus status)
 {
     if (FileFetchStarted != null)
         FileFetchStarted(this, status);
 }