public void CreateBookOnDiskFromTemplateStarter_IsTemplate_ButNotTemplateFactory() { var source = BloomFileLocator.GetFactoryBookTemplateDirectory("Template Starter"); var path = _starter.CreateBookOnDiskFromTemplate(source, _projectFolder.Path); var newMetaData = BookMetaData.FromFolder(path); Assert.That(newMetaData.IsSuitableForMakingShells, Is.True); Assert.That(newMetaData.IsSuitableForMakingTemplates, Is.False); }
/// <summary> /// Creates the .bloomd and bloomdigital folders /// </summary> private static CreateArtifactsExitCode CreateBloomDigitalArtifacts(string bookPath, string creator, string zippedBloomDOutputPath, string unzippedBloomDigitalOutputPath) { #if DEBUG // Useful for allowing debugging of Bloom while running the harvester //MessageBox.Show("Attach debugger now"); #endif var exitCode = CreateArtifactsExitCode.Success; using (var tempBloomD = TempFile.CreateAndGetPathButDontMakeTheFile()) { if (String.IsNullOrEmpty(zippedBloomDOutputPath)) { zippedBloomDOutputPath = tempBloomD.Path; } BookServer bookServer = _projectContext.BookServer; var metadata = BookMetaData.FromFolder(bookPath); bool isTemplateBook = metadata.IsSuitableForMakingShells; using (var folderForUnzipped = new TemporaryFolder("BloomCreateArtifacts_Unzipped")) { // Ensure directory exists, just in case. Directory.CreateDirectory(Path.GetDirectoryName(zippedBloomDOutputPath)); // Make the bloomd string unzippedPath = Publish.Android.BloomPubMaker.CreateBloomPub( zippedBloomDOutputPath, bookPath, bookServer, System.Drawing.Color.Azure, // TODO: What should this be? new Bloom.web.NullWebSocketProgress(), folderForUnzipped, creator, isTemplateBook); // Currently the zipping process does some things we actually need, like making the cover picture // transparent (BL-7437). Eventually we plan to separate the preparation and zipping steps (BL-7445). // Until that is done, the most reliable way to get an unzipped BloomD for our preview is to actually // unzip the BloomD. if (!String.IsNullOrEmpty(unzippedBloomDigitalOutputPath)) { SIL.IO.RobustIO.DeleteDirectory(unzippedBloomDigitalOutputPath, recursive: true); // In case the folder isn't already empty // Ensure directory exists, just in case. Directory.CreateDirectory(Path.GetDirectoryName(unzippedBloomDigitalOutputPath)); ZipFile.ExtractToDirectory(zippedBloomDOutputPath, unzippedBloomDigitalOutputPath); exitCode |= RenameBloomDigitalFiles(unzippedBloomDigitalOutputPath); } } } return(exitCode); }
public void CreateBookOnDiskFromTemplate_OriginalIsTemplate_CopyIsNotTemplate() { var source = BloomFileLocator.GetFactoryBookTemplateDirectory("Basic Book"); var originalMetaData = BookMetaData.FromFolder(source); Assert.That(originalMetaData.IsSuitableForMakingShells); var path = _starter.CreateBookOnDiskFromTemplate(source, _projectFolder.Path); var newMetaData = BookMetaData.FromFolder(path); Assert.That(newMetaData.IsSuitableForMakingShells, Is.False); }
/// <summary> /// Review: this is fragile and expensive. We're doing real internet traffic and creating real objects on S3 and parse.com /// which (to a very small extent) costs us real money. This will be slow. Also, under S3 eventual consistency rules, /// there is no guarantee that the data we just created will actually be retrievable immediately. /// </summary> /// <param name="bookName"></param> /// <param name="id"></param> /// <param name="uploader"></param> /// <param name="data"></param> /// <returns></returns> public Tuple <string, string> UploadAndDownLoadNewBook(string bookName, string id, string uploader, string data, bool isTemplate = false) { // Create a book folder with meta.json that includes an uploader and id and some other files. var originalBookFolder = MakeBook(bookName, id, uploader, data, true); if (isTemplate) { var metadata = BookMetaData.FromFolder(originalBookFolder); metadata.IsSuitableForMakingShells = true; metadata.WriteToFolder(originalBookFolder); } // The files that actually get uploaded omit some of the ones in the folder. // The only omitted one that messes up current unit tests is meta.bak var filesToUpload = Directory.GetFiles(originalBookFolder).Where(p => !p.EndsWith(".bak") && !p.Contains(BookStorage.PrefixForCorruptHtmFiles)); int fileCount = filesToUpload.Count(); Login(); //HashSet<string> notifications = new HashSet<string>(); var progress = new SIL.Progress.StringBuilderProgress(); var s3Id = _uploader.UploadBook(originalBookFolder, progress); var uploadMessages = progress.Text.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); var expectedFileCount = fileCount + 2; // should get one per file, plus one for metadata, plus one for book order #if DEBUG ++expectedFileCount; // and if in debug mode, then plus one for S3 ID #endif Assert.That(uploadMessages.Length, Is.EqualTo(expectedFileCount), "Uploaded file counts do not match"); Assert.That(progress.Text, Does.Contain( LocalizationManager.GetString("PublishTab.Upload.UploadingBookMetadata", "Uploading book metadata", "In this step, Bloom is uploading things like title, languages, & topic tags to the bloomlibrary.org database."))); Assert.That(progress.Text, Does.Contain(Path.GetFileName(filesToUpload.First()))); _uploader.WaitUntilS3DataIsOnServer(BloomS3Client.UnitTestBucketName, originalBookFolder); var dest = _workFolderPath.CombineForPath("output"); Directory.CreateDirectory(dest); _downloadedBooks.Clear(); var url = BookUpload.BloomS3UrlPrefix + BloomS3Client.UnitTestBucketName + "/" + s3Id; var newBookFolder = _downloader.HandleDownloadWithoutProgress(url, dest); Assert.That(Directory.GetFiles(newBookFolder).Length, Is.EqualTo(fileCount + 1), "Book order was not added during upload"); // book order is added during upload Assert.That(_downloadedBooks.Count, Is.EqualTo(1)); Assert.That(_downloadedBooks[0].FolderPath, Is.EqualTo(newBookFolder)); // Todo: verify that metadata was transferred to Parse.com return(new Tuple <string, string>(originalBookFolder, newBookFolder)); }
// Wait (up to three seconds) for data uploaded to become available. // Currently only used in unit testing. // I have no idea whether 3s is an adequate time to wait for 'eventual consistency'. So far it seems to work. internal void WaitUntilS3DataIsOnServer(string bookPath) { var s3Id = S3BookId(BookMetaData.FromFolder(bookPath)); var count = Directory.GetFiles(bookPath).Length; for (int i = 0; i < 30; i++) { var uploaded = _s3Client.GetBookFileCount(s3Id); if (uploaded >= count) { return; } Thread.Sleep(100); } throw new ApplicationException("S3 is very slow today"); }
// Wait (up to three seconds) for data uploaded to become available. // Currently only used in unit testing. // I have no idea whether 3s is an adequate time to wait for 'eventual consistency'. So far it seems to work. internal void WaitUntilS3DataIsOnServer(string bucket, string bookPath) { var s3Id = S3BookId(BookMetaData.FromFolder(bookPath)); // There's a few files we don't upload, but meta.bak is the only one that regularly messes up the count. // Some tests also deliberately include a _broken_ file to check they aren't uploaded, // so we'd better not wait for that to be there, either. var count = Directory.GetFiles(bookPath).Count(p => !p.EndsWith(".bak") && !p.Contains(BookStorage.PrefixForCorruptHtmFiles)); for (int i = 0; i < 30; i++) { var uploaded = _s3Client.GetBookFileCount(bucket, s3Id); if (uploaded >= count) { return; } Thread.Sleep(100); } throw new ApplicationException("S3 is very slow today"); }
/// <summary> /// Creates the .bloompub and bloomdigital folders /// </summary> private static CreateArtifactsExitCode CreateBloomDigitalArtifacts(string bookPath, string creator, string zippedBloomPubOutputPath, string unzippedBloomDigitalOutputPath) { #if DEBUG // Useful for allowing debugging of Bloom while running the harvester //MessageBox.Show("Attach debugger now"); #endif var exitCode = CreateArtifactsExitCode.Success; using (var tempBloomPub = TempFile.CreateAndGetPathButDontMakeTheFile()) { if (String.IsNullOrEmpty(zippedBloomPubOutputPath)) { zippedBloomPubOutputPath = tempBloomPub.Path; } BookServer bookServer = _projectContext.BookServer; var metadata = BookMetaData.FromFolder(bookPath); bool isTemplateBook = metadata.IsSuitableForMakingShells; // Build artifacts the same way from the harvester as on the user's local machine. // (similarly to a bulk publish operation) // See https://issues.bloomlibrary.org/youtrack/issue/BL-10300. var bookInfo = new BookInfo(bookPath, false); var settings = AndroidPublishSettings.GetPublishSettingsForBook(bookServer, bookInfo); using (var folderForUnzipped = new TemporaryFolder("BloomCreateArtifacts_Unzipped")) { // Ensure directory exists, just in case. Directory.CreateDirectory(Path.GetDirectoryName(zippedBloomPubOutputPath)); // Make the bloompub string unzippedPath = BloomPubMaker.CreateBloomPub( zippedBloomPubOutputPath, bookPath, bookServer, new Bloom.web.NullWebSocketProgress(), folderForUnzipped, creator, isTemplateBook, settings); // Currently the zipping process does some things we actually need, like making the cover picture // transparent (BL-7437). Eventually we plan to separate the preparation and zipping steps (BL-7445). // Until that is done, the most reliable way to get an unzipped BloomPUB for our preview is to actually // unzip the BloomPUB. if (!String.IsNullOrEmpty(unzippedBloomDigitalOutputPath)) { SIL.IO.RobustIO.DeleteDirectory(unzippedBloomDigitalOutputPath, recursive: true); // In case the folder isn't already empty // Ensure directory exists, just in case. Directory.CreateDirectory(Path.GetDirectoryName(unzippedBloomDigitalOutputPath)); ZipFile.ExtractToDirectory(zippedBloomPubOutputPath, unzippedBloomDigitalOutputPath); exitCode |= RenameBloomDigitalFiles(unzippedBloomDigitalOutputPath); } } } return(exitCode); }