private void m_btnUpdateFromBundle_Click(object sender, EventArgs e) { using (var dlg = new SelectProjectDlg(false, m_model.BundlePath)) { if (dlg.ShowDialog() == DialogResult.OK) { var selectedBundlePath = dlg.FileName; var bundle = new GlyssenBundle(selectedBundlePath); if (ConfirmProjectUpdateFromBundle(bundle)) { m_model.BundlePath = dlg.FileName; UpdatedBundle = bundle; HandleOkButtonClick(sender, e); } else { Analytics.Track("CancelledUpdateProjectFromBundleData", new Dictionary <string, string> { { "bundleLanguage", bundle.LanguageIso }, { "projectLanguage", m_model.IsoCode }, { "bundleID", bundle.Id }, { "projectID", m_model.PublicationId }, { "recordingProjectName", m_model.RecordingProjectName }, { "bundlePathChanged", (m_model.BundlePath != selectedBundlePath).ToString() } }); bundle.Dispose(); } } } }
public static bool GiveUserChanceToFindOriginalBundle(Project project) { using (var dlg = new SelectProjectDlg(false)) if (dlg.ShowDialog() == DialogResult.OK) { string invalidMessage = LocalizationManager.GetString("File.InvalidBundleMsg", "The selected file is not a valid text bundle. Would you like to try again?"); string invalidCaption = LocalizationManager.GetString("File.InvalidBundleMsg", "Invalid Bundle"); string bundlePath = dlg.FileName; if (Path.GetExtension(bundlePath) == DblBundleFileUtils.kDblBundleExtension) { try { var bundle = new GlyssenBundle(bundlePath); if (bundle.Id != project.Id) { string message = LocalizationManager.GetString("File.WrongBundleMsg", "The ID of the selected text bundle does not match this project. Would you like to try again?"); string caption = LocalizationManager.GetString("File.WrongBundle", "Wrong Bundle"); return(ErrorMessageWithRetry(message, caption, project)); } project.OriginalBundlePath = bundlePath; return(true); } catch { return(ErrorMessageWithRetry(invalidMessage, invalidCaption, project)); } } return(ErrorMessageWithRetry(invalidMessage, invalidCaption, project)); } return(false); }
private static Tuple <GlyssenBundle, TempFile> GetNewGlyssenBundleFromFile(bool includeLdml = true) { var bundleFile = TextBundleTests.CreateZippedTextBundleFromResources(includeLdml); var bundle = new GlyssenBundle(bundleFile.Path); bundle.Metadata.Language.Iso = bundle.Metadata.Id = GetUniqueBundleId(); return(new Tuple <GlyssenBundle, TempFile>(bundle, bundleFile)); }
private void m_btnUpdate_Click(object sender, EventArgs e) { if (m_model.IsLiveParatextProject) { UpdatedParatextProject = m_model.GetUpdatedParatextData(); if (UpdatedParatextProject != null) { Logger.WriteEvent($"Updating project {m_lblRecordingProjectName} from Paratext data {m_model.ParatextProjectName}"); HandleOkButtonClick(sender, e); } else { Analytics.Track("CancelledUpdateProjectFromParatextData", new Dictionary <string, string> { { "projectLanguage", m_model.IsoCode }, { "paratextPojectName", m_model.ParatextProjectName }, { "projectID", m_model.PublicationId }, { "recordingProjectName", m_model.RecordingProjectName } }); } } else { if (SelectBundleForProjectDlg.TryGetBundleName(m_model.RecordingProjectName, m_model.BundlePath, out string selectedBundlePath)) { var bundle = new GlyssenBundle(selectedBundlePath); if (ConfirmProjectUpdateFromBundle(bundle)) { Logger.WriteEvent($"Updating project {m_lblRecordingProjectName} from bundle {selectedBundlePath}"); m_model.BundlePath = selectedBundlePath; UpdatedBundle = bundle; HandleOkButtonClick(sender, e); } else { Analytics.Track("CancelledUpdateProjectFromBundleData", new Dictionary <string, string> { { "bundleLanguage", bundle.LanguageIso }, { "projectLanguage", m_model.IsoCode }, { "bundleID", bundle.Id }, { "projectID", m_model.PublicationId }, { "recordingProjectName", m_model.RecordingProjectName }, { "bundlePathChanged", (m_model.BundlePath != selectedBundlePath).ToString() } }); bundle.Dispose(); } } } }
private static bool UpgradeToCurrentDataFormatVersion(ApplicationMetadata info) { if (info.DataVersion >= Settings.Default.DataFormatVersion) { return(false); } Analytics.Track("DataVersionUpgrade", new Dictionary <string, string> { { "old", info.DataVersion.ToString(CultureInfo.InvariantCulture) }, { "new", Settings.Default.DataFormatVersion.ToString(CultureInfo.InvariantCulture) } }); switch (info.DataVersion) { case 0: foreach (var publicationFolder in Project.AllPublicationFolders) { var filesToMove = Directory.GetFiles(publicationFolder); if (!filesToMove.Any()) { continue; } var projectFilePath = Directory.GetFiles(publicationFolder, "*" + kOldProjectExtension).FirstOrDefault(); if (projectFilePath != null) { Exception exception; var metadata = GlyssenDblTextMetadata.Load <GlyssenDblTextMetadata>(projectFilePath, out exception); string recordingProjectName; if (exception != null) { // Just add a directory layer and don't worry about it for now. recordingProjectName = Path.GetFileName(publicationFolder); } else { if (metadata.Identification != null && !string.IsNullOrEmpty(metadata.Identification.Name)) { recordingProjectName = metadata.Identification.Name; } else { recordingProjectName = metadata.Id; } } recordingProjectName = Project.GetDefaultRecordingProjectName(recordingProjectName); var recordingProjectFolder = Path.Combine(publicationFolder, recordingProjectName); Directory.CreateDirectory(recordingProjectFolder); foreach (var file in filesToMove) { File.Move(file, Path.Combine(recordingProjectFolder, Path.GetFileName(file))); } if (Settings.Default.CurrentProject == projectFilePath) { Settings.Default.CurrentProject = Path.Combine(recordingProjectFolder, Path.GetFileName(projectFilePath)); } } } goto case 1; case 1: foreach (var recordingProjectFolder in Project.AllRecordingProjectFolders.ToList()) { var versificationPath = Path.Combine(recordingProjectFolder, DblBundleFileUtils.kVersificationFileName); if (!File.Exists(versificationPath)) { var projectFilePath = Directory.GetFiles(recordingProjectFolder, "*" + kOldProjectExtension).FirstOrDefault(); if (projectFilePath != null) { if (projectFilePath.Equals(SampleProject.SampleProjectFilePath, StringComparison.OrdinalIgnoreCase)) { File.WriteAllText(versificationPath, Resources.EnglishVersification); } else { Exception exception; var metadata = GlyssenDblTextMetadata.Load <GlyssenDblTextMetadata>(projectFilePath, out exception); var origBundlePath = metadata.OriginalPathBundlePath; if (string.IsNullOrEmpty(origBundlePath)) { try { Project.DeleteProjectFolderAndEmptyContainingFolders(recordingProjectFolder, true); } catch (Exception) { // Oh, well, we tried. Not the end of the world. } } else { var bundle = new GlyssenBundle(origBundlePath); var errorlogPath = Path.Combine(recordingProjectFolder, "errorlog.txt"); Versification.Table.HandleVersificationLineError = ex => { var msg = string.Format(LocalizationManager.GetString("DataMigration.InvalidVersificationFile", "Invalid versification file encountered during data migration. Errors must be fixed or subsequent " + "attempts to open this project will fail.\r\n" + "Project: {0}\r\n" + "Text release Bundle: {1}\r\n" + "Versification file: {2}\r\n" + "Error: {3}"), projectFilePath, origBundlePath, versificationPath, ex.Message); MessageBox.Show(msg, Program.kProduct, MessageBoxButtons.OK, MessageBoxIcon.Warning); File.WriteAllText(errorlogPath, msg); }; bundle.CopyVersificationFile(versificationPath); Project.LoadVersification(versificationPath); } } } } } Versification.Table.HandleVersificationLineError = null; goto case 2; case 2: foreach (var pgProjFile in Project.AllRecordingProjectFolders.SelectMany(d => Directory.GetFiles(d, "*" + kOldProjectExtension))) { var newName = Path.ChangeExtension(pgProjFile, Project.kProjectFileExtension); File.Move(pgProjFile, newName); if (Settings.Default.CurrentProject == pgProjFile) { Settings.Default.CurrentProject = newName; } } break; default: throw new Exception("No migration found from the existing data version!"); } info.DataVersion = Settings.Default.DataFormatVersion; return(true); }
private static bool UpgradeToCurrentDataFormatVersion(ApplicationMetadata info) { if (info.DataVersion >= Settings.Default.DataFormatVersion) { return(false); } bool retVal = true; Analytics.Track("DataVersionUpgrade", new Dictionary <string, string> { { "old", info.DataVersion.ToString(CultureInfo.InvariantCulture) }, { "new", Settings.Default.DataFormatVersion.ToString(CultureInfo.InvariantCulture) } }); switch (info.DataVersion) { case 0: foreach (var publicationFolder in Project.AllPublicationFolders) { var filesToMove = Directory.GetFiles(publicationFolder); if (!filesToMove.Any()) { continue; } var projectFilePath = Directory.GetFiles(publicationFolder, "*" + kOldProjectExtension).FirstOrDefault(); if (projectFilePath != null) { Exception exception; var metadata = GlyssenDblTextMetadata.Load <GlyssenDblTextMetadata>(projectFilePath, out exception); string recordingProjectName; if (exception != null) { // Just add a directory layer and don't worry about it for now. recordingProjectName = Path.GetFileName(publicationFolder); } else { if (metadata.Identification != null && !string.IsNullOrEmpty(metadata.Identification.Name)) { recordingProjectName = metadata.Identification.Name; } else { recordingProjectName = metadata.Id; } } recordingProjectName = Project.GetDefaultRecordingProjectName(recordingProjectName); var recordingProjectFolder = Path.Combine(publicationFolder, recordingProjectName); Directory.CreateDirectory(recordingProjectFolder); foreach (var file in filesToMove) { File.Move(file, Path.Combine(recordingProjectFolder, Path.GetFileName(file))); } if (Settings.Default.CurrentProject == projectFilePath) { Settings.Default.CurrentProject = Path.Combine(recordingProjectFolder, Path.GetFileName(projectFilePath)); } } } goto case 1; case 1: foreach (var recordingProjectFolder in Project.AllRecordingProjectFolders.ToList()) { var versificationPath = Path.Combine(recordingProjectFolder, DblBundleFileUtils.kVersificationFileName); if (!File.Exists(versificationPath)) { var projectFilePath = Directory.GetFiles(recordingProjectFolder, "*" + kOldProjectExtension).FirstOrDefault(); if (projectFilePath != null) { if (projectFilePath.Equals(SampleProject.SampleProjectFilePath, StringComparison.OrdinalIgnoreCase)) { File.WriteAllText(versificationPath, Resources.EnglishVersification); } else { Exception exception; var metadata = GlyssenDblTextMetadata.Load <GlyssenDblTextMetadata>(projectFilePath, out exception); var origBundlePath = metadata.OriginalReleaseBundlePath; if (string.IsNullOrEmpty(origBundlePath)) { // Note: We didn't support Paratext-based projects until settings version 3 (Glyssen 1.1), // so for this step in the migration process (going from 0 to 1), any project without // OriginalReleaseBundlePath set is invalid (possibly from a really early version of Glyssen // or some g;itch arising from development activity or external mangling of the file). So // we should be able to safely blow this away. try { Project.DeleteProjectFolderAndEmptyContainingFolders(recordingProjectFolder, true); } catch (Exception) { // Oh, well, we tried. Not the end of the world. } } else { var bundle = new GlyssenBundle(origBundlePath); var errorlogPath = Path.Combine(recordingProjectFolder, "errorlog.txt"); bundle.CopyVersificationFile(versificationPath); try { ProjectBase.LoadVersification(versificationPath); } catch (InvalidVersificationLineException ex) { var msg = string.Format(LocalizationManager.GetString("DataMigration.InvalidVersificationFile", "Invalid versification file encountered during data migration. Errors must be fixed or subsequent " + "attempts to open this project will fail.\r\n" + "Project: {0}\r\n" + "Text release Bundle: {1}\r\n" + "Versification file: {2}\r\n" + "Error: {3}"), projectFilePath, origBundlePath, versificationPath, ex.Message); MessageBox.Show(msg, GlyssenInfo.kProduct, MessageBoxButtons.OK, MessageBoxIcon.Warning); File.WriteAllText(errorlogPath, msg); } } } } } } goto case 2; case 2: foreach (var pgProjFile in Project.AllRecordingProjectFolders.SelectMany(d => Directory.GetFiles(d, "*" + kOldProjectExtension))) { var newName = Path.ChangeExtension(pgProjFile, Constants.kProjectFileExtension); File.Move(pgProjFile, newName); if (Settings.Default.CurrentProject == pgProjFile) { Settings.Default.CurrentProject = newName; } } break; // No need to go to case 3, since the problem it fixes would only have been caused by a version of Glyssen with data version 3 case 3: try { RobustIO.DeleteDirectory(Path.GetDirectoryName(SampleProject.SampleProjectFilePath) + " Audio", true); } catch (IOException e) { Logger.WriteError("Unable to clean up superfluous sample Audio Audio folder.", e); } var safeReplacements = new List <Tuple <string, string> >(); var unsafeReplacements = new List <Tuple <string, string> >(); foreach (var folder in Project.AllRecordingProjectFolders.Where(d => d.EndsWith(" Audio Audio"))) { // Because of the way this bug (PG-1192) worked, the most likely thing is that the "correct" // version of the project will have been initially created but then all the actual work will // have gotten saved into the "incorrect" version. If this looks to be the case, we can // probably safely delete the correct one and then rename the incorrect one to have the correct // name. var baseFolder = Path.GetDirectoryName(folder); Debug.Assert(baseFolder != null); var languageFolder = Path.GetDirectoryName(baseFolder); Debug.Assert(languageFolder != null); var langCode = Path.GetFileName(languageFolder); Debug.Assert(langCode != null); var incorrectProjName = Path.GetFileName(folder); Debug.Assert(incorrectProjName != null); var correctProjectName = incorrectProjName.Substring(0, incorrectProjName.Length - " Audio".Length); var correctProjectFolder = Path.Combine(baseFolder, correctProjectName); if (Directory.Exists(correctProjectFolder)) { var glyssenProjFilename = langCode + Constants.kProjectFileExtension; var incorrectProjectFilePath = Path.Combine(folder, glyssenProjFilename); var correctProjectFilePath = Path.Combine(correctProjectFolder, glyssenProjFilename); var finfoIncorrectProject = new FileInfo(incorrectProjectFilePath); var finfoCorrectProject = new FileInfo(correctProjectFilePath); if (finfoCorrectProject.Exists && finfoIncorrectProject.Exists) { if (finfoCorrectProject.LastWriteTimeUtc < finfoIncorrectProject.LastWriteTimeUtc) { var books = Directory.GetFiles(correctProjectFolder, "???.xml").Where(b => Canon.IsBookIdValid(Path.GetFileNameWithoutExtension(b))) .Select(XmlSerializationHelper.DeserializeFromFile <BookScript>); foreach (var book in books) { // If book == null, there was a problem loading it. It may be locked or be in some incompatible format. // In any case, we shouldn't risk assuming we can safely replace it. if (book == null || book.GetScriptBlocks().Any(b => b.UserConfirmed || b.MatchesReferenceText)) { unsafeReplacements.Add(new Tuple <string, string>(folder, correctProjectFolder)); break; } } if (unsafeReplacements.LastOrDefault()?.Item1 == folder) { continue; } try { var projToBackUp = Project.Load(correctProjectFilePath); projToBackUp.CreateBackup("Overwritten by migration 3-4"); } catch (Exception e) { Logger.WriteError("Unable to load project and create backup", e); safeReplacements.Add(new Tuple <string, string>(folder, correctProjectFolder)); continue; } try { RobustIO.DeleteDirectory(correctProjectFolder, true); RobustIO.MoveDirectory(folder, correctProjectFolder); } catch (IOException e) { Logger.WriteError("Unable to replace project after making backup", e); Console.WriteLine(e); unsafeReplacements.Add(new Tuple <string, string>(folder, correctProjectFolder)); } } else { unsafeReplacements.Add(new Tuple <string, string>(folder, correctProjectFolder)); } } } } if (safeReplacements.Any()) { string fmt; if (safeReplacements.Count == 1) { fmt = LocalizationManager.GetString("DataMigration.ConfirmReplacementOfAudioAudio", "Doing this will replace the existing project by the same name, which was originally created by {0}. " + "Since none of the blocks in the project to be overwritten have any user decisions recorded, this seems " + "to be safe, but since {0} failed to make a backup, you need to confirm this. If you choose not to confirm " + "this action, you can either clean up the problem project yourself or verify that is is safe and then restart " + "{0}. You will be asked about this each time you start the program as long as this problem remains unresolved.\r\n" + "Confirm overwriting?", "Param: \"Glyssen\" (product name); " + "This follows the \"AudioAudioProblemPreambleSingle\"."); } else { fmt = LocalizationManager.GetString("DataMigration.ConfirmReplacementsOfAudioAudio", "Doing this will replace the existing projects by the same name, which were originally created by {0}. " + "Since none of the blocks in the projects to be overwritten have any user decisions recorded, this seems " + "to be safe, but since {0} failed to make a backup, you need to confirm this. If you choose not to confirm " + "this action, you can either clean up the problem projects yourself or verify that is is safe and then restart " + "{0}. You will be asked about this each time you start the program as long as these problems remains unresolved.\r\n" + "Confirm overwriting?", "Param: \"Glyssen\" (product name); " + "This follows the \"AudioAudioProblemPreambleMultiple\"."); } var msg = GetAudioAudioProblemPreamble(safeReplacements.Count) + String.Join(Environment.NewLine, safeReplacements.Select(r => r.Item1)) + Environment.NewLine + Environment.NewLine + String.Format(fmt, GlyssenInfo.kProduct); if (DialogResult.Yes == MessageBox.Show(msg, GlyssenInfo.kProduct, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2)) { foreach (var replacement in safeReplacements) { RobustIO.DeleteDirectory(replacement.Item2, true); RobustIO.MoveDirectory(replacement.Item1, replacement.Item2); } safeReplacements.Clear(); } } if (unsafeReplacements.Any()) { string fmt; if (unsafeReplacements.Count == 1) { fmt = LocalizationManager.GetString("DataMigration.NoticeToManuallyFixAudioAudioProject", "However, doing this would replace the existing project by the same name. " + "Since {0} was unable to determine whether this was safe or otherwise failed to do the replacement, it is recommended " + "that you clean up the problem project yourself. You are encouraged to contact a local support person if needed or " + "seek help on {1}. You will be reminded about this each time you start the program as long as this problem remains unresolved.", "Param 0: \"Glyssen\" (product name); " + "Param 1: \"https://community.scripture.software.sil.org/\"" + "This follows the \"AudioAudioProblemPreambleSingle\"."); } else { fmt = LocalizationManager.GetString("DataMigration.NoticeToManuallyFixAudioAudioProjects", "However, doing this would replace the existing projects by the same name. " + "Since {0} was unable to determine whether this was safe or otherwise failed to do the replacements, it is recommended " + "that you clean up the problem projects yourself. You are encouraged to contact a local support person if needed or " + "seek help on {1}. You will be reminded about this each time you start the program as long as these problems remains unresolved.", "Param 0: \"Glyssen\" (product name); " + "Param 1: \"https://community.scripture.software.sil.org/\"" + "This follows the \"AudioAudioProblemPreambleMultiple\"."); } var msg = GetAudioAudioProblemPreamble(unsafeReplacements.Count) + String.Join(Environment.NewLine, unsafeReplacements.Select(r => r.Item1)) + Environment.NewLine + Environment.NewLine + String.Format(fmt, GlyssenInfo.kProduct, Constants.kSupportSite); MessageBox.Show(msg, GlyssenInfo.kProduct, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } if (unsafeReplacements.Any() || safeReplacements.Any()) { retVal = false; } break; default: throw new Exception("No migration found from the existing data version!"); } if (retVal) { info.DataVersion = Settings.Default.DataFormatVersion; } return(retVal); }
private bool ConfirmProjectUpdateFromBundle(GlyssenBundle bundle) { StringBuilder msg = new StringBuilder(); var oldValueFormat = LocalizationManager.GetString("Project.UpdateFromBundle.OldValue", "Old value: {0}"); var newValueFormat = LocalizationManager.GetString("Project.UpdateFromBundle.NewValue", "New value: {0}"); if (bundle.LanguageIso != m_model.IsoCode) { msg.Append(Environment.NewLine); msg.Append(LocalizationManager.GetString("Project.UpdateFromBundle.Language", "Language")); msg.Append(Environment.NewLine); msg.Append(" "); var oldLanguage = string.IsNullOrEmpty(m_model.LanguageName) ? m_model.IsoCode : string.Format("{0} ({1})", m_model.LanguageName, m_model.IsoCode); msg.AppendFormat(oldValueFormat, oldLanguage); msg.Append(Environment.NewLine); msg.Append(" "); msg.AppendFormat(newValueFormat, bundle.LanguageAsString); msg.Append(Environment.NewLine); } if (bundle.Id != m_model.PublicationId) { msg.Append(Environment.NewLine); msg.Append(LocalizationManager.GetString("Project.UpdateFromBundle.Id", "ID")); msg.Append(Environment.NewLine); msg.Append(" "); msg.AppendFormat(oldValueFormat, m_model.PublicationId); msg.Append(Environment.NewLine); msg.Append(" "); msg.AppendFormat(newValueFormat, bundle.Id); msg.Append(Environment.NewLine); } if (msg.Length > 0) { msg.Insert(0, Environment.NewLine); msg.Insert(0, LocalizationManager.GetString("Project.UpdateFromBundle.UpdatedBundleMismatch", "The metadata of the selected text release bundle does not match the current project. If you continue with this update, the following metadata will be changed:")); // This isn't necessarily "required" or "expected", but it seems useful to report if (bundle.Name != m_model.PublicationName) { msg.Append(Environment.NewLine); msg.Append(LocalizationManager.GetString("Project.UpdateFromBundle.PublicationName", "Publication name")); msg.Append(Environment.NewLine); msg.Append(" "); msg.AppendFormat(oldValueFormat, m_model.PublicationName); msg.Append(Environment.NewLine); msg.Append(" "); msg.AppendFormat(newValueFormat, bundle.Name); msg.Append(Environment.NewLine); } msg.Append(Environment.NewLine); msg.Append(LocalizationManager.GetString("Project.UpdateFromBundle.AllowUpdate", "Do you want to continue with this update?")); return(MessageBox.Show(this, msg.ToString(), LocalizationManager.GetString("Project.UpdateFromBundle.ConfirmUpdate", "Confirm Update"), MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes); } return(true); }
private void LoadBundle(string bundlePath) { GlyssenBundle bundle = null; if (!LoadAndHandleApplicationExceptions(() => { bundle = new GlyssenBundle(bundlePath); })) { SetProject(null); return; } string projFilePath; // See if we already have project(s) for this bundle and give the user the option of opening an existing project instead. var publicationFolder = Project.GetPublicationFolderPath(bundle); if (Directory.Exists(publicationFolder) && Directory.GetDirectories(publicationFolder).Any(f => Directory.GetFiles(f, "*" + ProjectBase.kProjectFileExtension) .Any(filename => GlyssenDblTextMetadata.GetRevisionOrChangesetId(filename) == bundle.Metadata.RevisionOrChangesetId))) { using (var dlg = new SelectExistingProjectDlg(bundle)) { dlg.ShowDialog(this); if (dlg.SelectedProject == null) { // User clicked the red X. Let's just pretend this whole nightmare never happened. return; } projFilePath = dlg.SelectedProject; } } else { projFilePath = Project.GetDefaultProjectFilePath(bundle); } var recordingProjectName = Path.GetFileName(Path.GetDirectoryName(projFilePath)); if (File.Exists(projFilePath)) { if (GlyssenDblTextMetadata.GetRevisionOrChangesetId(projFilePath) == bundle.Metadata.RevisionOrChangesetId) { LoadProject(projFilePath); bundle.Dispose(); return; } // If we get here, then the Select Existing Project dialog was not displayed, but there is // already a project with the same path (i.e., for a different revision). So we need to // generate a unique revision-specific project path. // TODO (PG-222): Before blindly creating a new project, we probably need to prompt the // user to see if they want to upgrade an existing project instead. If there are multiple // candidate projects, we'll need to present a list. var baserecordingProjectName = recordingProjectName; recordingProjectName = string.Format("{0} (Rev {1})", baserecordingProjectName, bundle.Metadata.Revision); var path = Project.GetProjectFilePath(bundle.LanguageIso, bundle.Id, recordingProjectName); for (int i = 1; File.Exists(path); i++) { recordingProjectName = string.Format("{0} (Rev {1}.{2})", baserecordingProjectName, bundle.Metadata.Revision, i); path = Project.GetProjectFilePath(bundle.LanguageIso, bundle.Id, recordingProjectName); } } Versification.Table.HandleVersificationLineError = null; try { SetProject(new Project(bundle, recordingProjectName)); } catch (InvalidVersificationLineException ex) { var error = ex.Message; int i = error.IndexOf("\n", StringComparison.Ordinal); if (i > 0) { error = error.Substring(0, i); } var msg = string.Format(LocalizationManager.GetString("Project.InvalidVersificationFile", "Invalid versification file in text release bundle. Unable to create project.\r\n" + "Text release Bundle: {0}\r\n" + "Versification file: {1}\r\n" + "Error: {2}"), bundlePath, DblBundleFileUtils.kVersificationFileName, error); MessageBox.Show(this, msg, Program.kProduct, MessageBoxButtons.OK, MessageBoxIcon.Warning); SetProject(null); } bundle.Dispose(); }