private static void Import(Opts opts) { bool createdTempFile = false; if(opts.FilePath.StartsWith("http:") || opts.FilePath.StartsWith("https:")) { DreamMessage packageMessage = Plug.New(opts.FilePath).InvokeEx("GET", DreamMessage.Ok(), new Result<DreamMessage>()).Wait(); if(!packageMessage.IsSuccessful) { throw new Exception(string.Format("Unable to download package from '{0}'", opts.FilePath)); } opts.FilePath = Path.GetTempFileName(); opts.Archive = true; createdTempFile = true; using(Stream tempStream = File.Create(opts.FilePath)) { packageMessage.ToStream().CopyTo(tempStream, packageMessage.ContentLength, new Result<long>()).Wait(); } } IPackageReader packageReader; if(opts.Archive) { if(!File.Exists(opts.FilePath)) { throw new ConfigurationException("No such file: {0}", opts.FilePath); } if(opts.Test) { return; } packageReader = new ArchivePackageReader(opts.FilePath); } else { if(!Directory.Exists(opts.FilePath)) { throw new ConfigurationException("No such directory: {0}", opts.FilePath); } if(opts.Test) { return; } packageReader = new FilePackageReader(opts.FilePath); } ImportManager manager; try { var manifest = packageReader.ReadManifest(new Result<XDoc>()).Wait(); FixupManifest(manifest, opts); var forceOverwrite = !(opts.PreserveLocalChanges ?? true); var importer = opts.ImportRelto.HasValue ? Importer.CreateAsync(opts.DekiApi, manifest, opts.ImportRelto.Value, forceOverwrite, new Result<Importer>()).Wait() : Importer.CreateAsync(opts.DekiApi, manifest, opts.ImportReltoPath, forceOverwrite, new Result<Importer>()).Wait(); manager = new ImportManager(importer, packageReader); } catch(Exception e) { if(createdTempFile) { File.Delete(opts.FilePath); } throw new Exception(string.Format("Import failed: {0}", e.Message), e); } manager.MaxRetries = opts.Retries; Result result = manager.ImportAsync(new Result()); int completed = 0; Console.WriteLine("Importing:"); while(!result.HasFinished) { Thread.Sleep(200); if(manager.CompletedItems <= completed) { continue; } if(SysUtil.IsUnix) { Console.WriteLine(" {0} of {1} files ({2:0}%)", manager.CompletedItems, manager.TotalItems, 100.0 * manager.CompletedItems / manager.TotalItems); } else { Console.Write(" {0} of {1} files ({2:0}%) \r", manager.CompletedItems, manager.TotalItems, 100.0 * manager.CompletedItems / manager.TotalItems); } completed = manager.CompletedItems; } if(!SysUtil.IsUnix) { Console.WriteLine(); } if(createdTempFile) { File.Delete(opts.FilePath); } if(result.HasException) { ImportException importException = result.Exception as ImportException; if(importException != null) { Console.WriteLine("Import failed on Item:\r\n{0}", importException.ManifestItem.ToPrettyString()); } throw new Exception(string.Format("Import failed: {0}", result.Exception.Message), result.Exception); } }
private IEnumerator<IYield> UpdatePackages_Helper(Plug api, string wikiId, string apikey, bool force, bool init, Result<XDoc> result) { try { _status = PackageUpdaterStatus.Importing; yield return Coroutine.Invoke(AuthenticateImportUser, api, wikiId, apikey, new Result<Plug>()).Set(x => api = x); XDoc license = null; yield return api.At("license").With("apikey", apikey).Get(new Result<XDoc>()).Set(x => license = x); var importReport = new XDoc("packages"); var first = true; foreach(var directory in Directory.GetDirectories(_templatePackagePath)) { var directoryName = Path.GetFileName(directory); string restriction = null; if(directoryName.EqualsInvariantIgnoreCase("public")) { restriction = "Public"; } else if(directoryName.EqualsInvariantIgnoreCase("semi-public")) { restriction = "Semi-Public"; } else if(directoryName.EqualsInvariantIgnoreCase("private")) { restriction = "Private"; } foreach(var package in Directory.GetFiles(directory, "*.mt*").OrderBy(x => x)) { var ext = Path.GetExtension(package); if(!(ext.EqualsInvariantIgnoreCase(".mtarc") || ext.EqualsInvariantIgnoreCase(".mtapp"))) { continue; } if(!first) { importReport.End(); } first = false; importReport.Start("package").Elem("path", package); ArchivePackageReader packageReader; _log.DebugFormat("contemplating import of '{0}' for '{1}'", package, wikiId); try { packageReader = new ArchivePackageReader(package); } catch(Exception e) { SetError(importReport, wikiId, "error", e, "Unable to open package."); continue; } Result<XDoc> manifestResult; yield return manifestResult = packageReader.ReadManifest(new Result<XDoc>()).Catch(); if(manifestResult.HasException) { SetError(importReport, wikiId, "error", manifestResult.Exception, "Unable to read package manifest."); continue; } var manifest = manifestResult.Value; // check for required capabilities var capabilitiesSatisfied = true; foreach(var capability in manifest["capability"]) { var capabilityName = capability["@name"].AsText; var capabilityValue = capability["@value"].AsText.IfNullOrEmpty("enabled"); if(string.IsNullOrEmpty(capabilityName)) { continue; } var licenseCapabilityValue = DekiLicense.GetCapability(license, capabilityName) ?? ""; if(!string.IsNullOrEmpty(capabilityName) && licenseCapabilityValue.EqualsInvariant(capabilityValue)) { continue; } capabilitiesSatisfied = false; SetError(importReport, wikiId, "error", null, "Missing capability '{0}' or incorrect capability value, expected '{1}' and got '{2}'.", capabilityName, capabilityValue, licenseCapabilityValue); } if(!capabilitiesSatisfied) { continue; } // add security xml if we are in a restriction enforcing path if(!string.IsNullOrEmpty(restriction)) { manifest.Start("security") .Start("permissions.page") .Elem("restriction", restriction) .End() .End(); } // if package predates @date.created, take file modified var dateCreated = manifest["@date.created"].AsDate ?? new FileInfo(package).LastWriteTime; // check whether we should import this package var filename = Path.GetFileName(package); var importOnce = manifest["@import-once"].AsBool ?? false; var initPackage = manifest["@init-only"].AsBool ?? false; importReport.Elem("name", filename).Attr("date.created", dateCreated).Attr("preserve-local", manifest["@preserve-local"].AsBool ?? false); var importPropertyName = XUri.EncodeSegment(PACKAGE_PROPERTY_NS + filename); if(initPackage && !init && !force) { SetError(importReport, wikiId, "skipped", null, "package '{0}' is an init package and neither init or force flags were set, skipping", package); continue; } if(force && !importOnce) { _log.DebugFormat("force is set and package '{0}' is not marked as oneTimeOnly, proceeding with import", package); } else { DreamMessage propertyResponse = null; yield return api.At("site", "properties", importPropertyName).Get(new Result<DreamMessage>()).Set(x => propertyResponse = x); if(propertyResponse.IsSuccessful) { var importedPackage = propertyResponse.ToDocument(); var importedPackageDate = importedPackage["date.created"].AsDate; if(!importedPackageDate.HasValue) { _log.WarnFormat("unable to retrieve imported package date.created for '{0}', treating package as new", package); } else if(dateCreated > importedPackageDate.Value) { _log.DebugFormat("package '{0}' is newer, proceed with import ({1} > {2}", package, dateCreated, importedPackageDate.Value); } else { SetError(importReport, wikiId, "skipped", null, "package '{0}' is not newer, skip import ({1} <= {2}.)", package, dateCreated, importedPackageDate.Value); continue; } } else if(propertyResponse.Status == DreamStatus.Unauthorized) { _log.WarnFormat("apiuri has lost its authentication, dropping out"); throw new UnauthorizedAccessException("Authentication for was lost"); } else { _log.DebugFormat("package '{0}' has not previously been imported, proceeding with import", package); } } // import package Result<Importer> importerResult; yield return importerResult = Importer.CreateAsync(api, manifest, "/", new Result<Importer>()).Catch(); if(importerResult.HasException) { SetError(importReport, wikiId, "error", importerResult.Exception, "Unable to create importer for package."); continue; } var importer = importerResult.Value; var importManager = new ImportManager(importer, packageReader); Result importResult; yield return importResult = importManager.ImportAsync(new Result()).Catch(); if(importResult.HasException) { SetError(importReport, wikiId, "error", importResult.Exception, "Import did not complete successfully."); continue; } // write import data as site property yield return api.At("site", "properties", importPropertyName) .With("abort", "never") .With("description", string.Format("Import of package '{0}'", filename)) .Put(new XDoc("package").Elem("date.created", dateCreated), new Result<DreamMessage>()); importReport.Start("status").Attr("code", "ok").End(); _log.DebugFormat("sucessfully imported package '{0}'", package); } } if(!first) { importReport.End(); } result.Return(importReport); yield break; } finally { _status = PackageUpdaterStatus.Idle; } }