public void FinishCloning(Dictionary<string, string> commandLineArgs, string cloneLocation, string expectedPathToClonedRepository)
        {
            // "obtain"
            //		'cloneLocation' will be a new folder at the $fwroot main project location, such as $fwroot\foo.
            //		Move the lift repo down into $fwroot\foo\OtherRepositories\foo_LIFT folder

            // Check for Lift version compatibility.
            cloneLocation = RemoveAppendedLiftIfNeeded(cloneLocation);
            var otherReposDir = Path.Combine(cloneLocation, Utilities.OtherRepositories);
            if (!Directory.Exists(otherReposDir))
            {
                Directory.CreateDirectory(otherReposDir);
            }
            _liftFolder = Utilities.LiftOffset(cloneLocation);

            var actualCloneResult = new ActualCloneResult
            {
                // Be a bit pessimistic at first.
                CloneResult = null,
                ActualCloneFolder = null,
                FinalCloneResult = FinalCloneResult.ExistingCloneTargetFolder
            };

            // Move the repo from its temp home in cloneLocation into new home.
            // The original location, may not be on the same device, so it may be a copy+delete, rather than a formal move.
            // At the end of the day, cloneLocation and its parent temp folder need to be deleted. MakeLocalCloneAndRemoveSourceParentFolder aims to do all of it.
            MakeLocalClone(cloneLocation, _liftFolder);
            actualCloneResult.ActualCloneFolder = _liftFolder;
            actualCloneResult.FinalCloneResult = FinalCloneResult.Cloned;

            // Update to the head of the desired branch, if possible.
            UpdateToTheCorrectBranchHeadIfPossible(_liftFolder, "LIFT" + commandLineArgs["-liftmodel"], actualCloneResult);

            switch (actualCloneResult.FinalCloneResult)
            {
                case FinalCloneResult.ExistingCloneTargetFolder:
                    MessageBox.Show(CommonResources.kFlexProjectExists, CommonResources.kObtainProject, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    Directory.Delete(cloneLocation, true);
                    _liftFolder = null;
                    break;
                case FinalCloneResult.FlexVersionIsTooOld:
                    MessageBox.Show(CommonResources.kFlexUpdateRequired, CommonResources.kObtainProject, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    Directory.Delete(cloneLocation, true);
                    _liftFolder = null;
                    break;
            }

            // Delete all old repo folders and files from 'cloneLocation'.
            foreach (var dir in Directory.GetDirectories(cloneLocation).Where(directory => !directory.Contains(Utilities.OtherRepositories)))
            {
                Directory.Delete(dir, true);
            }
            foreach (var file in Directory.GetFiles(cloneLocation))
            {
                File.Delete(file);
            }
        }
        public void FinishCloning(Dictionary<string, string> commandLineArgs, string cloneLocation, string expectedPathToClonedRepository)
        {
            var actualCloneResult = new ActualCloneResult
                {
                    // Be a bit pessimistic at first.
                    CloneResult = null,
                    ActualCloneFolder = null,
                    FinalCloneResult = FinalCloneResult.ExistingCloneTargetFolder
                };

            _newProjectFilename = Path.GetFileName(cloneLocation) + Utilities.FwXmlExtension;
            _newFwProjectPathname = Path.Combine(cloneLocation, _newProjectFilename);

            // Check the actual FW model number in the '-fwmodel' of 'commandLineArgs' parm.
            // Update to the head of the desired branch, if possible.
            UpdateToTheCorrectBranchHeadIfPossible(commandLineArgs, actualCloneResult, cloneLocation);

            _gotClone = false;
            switch (actualCloneResult.FinalCloneResult)
            {
                case FinalCloneResult.ExistingCloneTargetFolder:
                    MessageBox.Show(CommonResources.kFlexProjectExists, CommonResources.kObtainProject, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    Directory.Delete(cloneLocation, true);
                    _newFwProjectPathname = null;
                    return;
                case FinalCloneResult.FlexVersionIsTooOld:
                    MessageBox.Show(actualCloneResult.Message, CommonResources.kObtainProject, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    Directory.Delete(cloneLocation, true);
                    _newFwProjectPathname = null;
                    return;
                case FinalCloneResult.Cloned:
                    _gotClone = true;
                    break;
            }

            FLExProjectUnifier.PutHumptyTogetherAgain(new NullProgress(), false, _newFwProjectPathname);
        }
		private static void UpdateToTheCorrectBranchHeadIfPossible(Dictionary<string, string> commandLineArgs,
				ActualCloneResult cloneResult,
				string cloneLocation)
		{
			var repo = new HgRepository(cloneLocation, new NullProgress());
			Dictionary<string, Revision> allHeads = Utilities.CollectAllBranchHeads(cloneLocation);
			var desiredBranchName = commandLineArgs["-fwmodel"];
			var desiredModelVersion = uint.Parse(desiredBranchName);
			Revision desiredRevision;
			if (!allHeads.TryGetValue(desiredBranchName, out desiredRevision))
			{
				// Remove any that are too high.
				var gonerKeys = new HashSet<string>();
				foreach (var headKvp in allHeads)
				{
					uint currentVersion;
					if (headKvp.Key == Default)
					{
						repo.Update(headKvp.Value.Number.LocalRevisionNumber);
						var modelVersion = FLExProjectUnifier.GetModelVersion(cloneLocation);
						currentVersion = (modelVersion == null)
											 ? uint.MaxValue // Get rid of the initial default commit by making it max for uint. It had no model version file.
											 : uint.Parse(modelVersion);
					}
					else
					{
						currentVersion = uint.Parse(headKvp.Value.Branch);
					}
					if (currentVersion > desiredModelVersion)
					{
						gonerKeys.Add((headKvp.Key == Default) ? Default : headKvp.Key);
					}
				}
				foreach (var goner in gonerKeys)
				{
					allHeads.Remove(goner);
				}

				// Replace 'default' with its real model number.
				if (allHeads.ContainsKey(Default))
				{
					repo.Update(allHeads[Default].Number.LocalRevisionNumber);
					var modelVersion = FLExProjectUnifier.GetModelVersion(cloneLocation);
					if (modelVersion != null)
					{
						if (allHeads.ContainsKey(modelVersion))
						{
							// Pick the highest revision of the two.
							var defaultHead = allHeads[Default];
							var otherHead = allHeads[modelVersion];
							var defaultRevisionNumber = int.Parse(defaultHead.Number.LocalRevisionNumber);
							var otherRevisionNumber = int.Parse(otherHead.Number.LocalRevisionNumber);
							allHeads[modelVersion] = defaultRevisionNumber > otherRevisionNumber ? defaultHead : otherHead;
						}
						else
						{
							allHeads.Add(modelVersion, allHeads[Default]);
						}
					}
					allHeads.Remove(Default);
				}

				// 'default' is no longer present in 'allHeads'.
				// If all of them are higher, then it is a no go.
				if (allHeads.Count == 0)
				{
					// No useable model version, so bailout with a message to the user telling them they are 'toast'.
					cloneResult.FinalCloneResult = FinalCloneResult.FlexVersionIsTooOld;
					cloneResult.Message = CommonResources.kFlexUpdateRequired;
					Directory.Delete(cloneLocation, true);
					return;
				}

				// Now. get to the real work.
				var sortedRevisions = new SortedList<uint, Revision>();
				foreach (var kvp in allHeads)
				{
					sortedRevisions.Add(uint.Parse(kvp.Key), kvp.Value);
				}
				desiredRevision = sortedRevisions.Values[sortedRevisions.Count - 1];
			}
			repo.Update(desiredRevision.Number.LocalRevisionNumber);
			cloneResult.ActualCloneFolder = cloneLocation;
			cloneResult.FinalCloneResult = FinalCloneResult.Cloned;
		}
        internal static void UpdateToTheCorrectBranchHeadIfPossible(string cloneLocation, string desiredBranchName, ActualCloneResult cloneResult)
        {
            var repo = new HgRepository(cloneLocation, new NullProgress());
            Dictionary<string, Revision> allHeads = Utilities.CollectAllBranchHeads(cloneLocation);
            var desiredModelVersion = float.Parse(desiredBranchName.Replace("LIFT", null));
            Revision desiredRevision;
            if (!allHeads.TryGetValue(desiredBranchName, out desiredRevision))
            {
                // Remove any that are too high.
                var gonerKeys = new HashSet<string>();
                foreach (var headKvp in allHeads)
                {
                    float currentVersion;
                    if (headKvp.Key == Default)
                    {
                        repo.Update(headKvp.Value.Number.LocalRevisionNumber);
                        currentVersion = GetLiftVersionNumber(cloneLocation);
                    }
                    else
                    {
                        currentVersion = float.Parse(headKvp.Value.Branch);
                    }
                    if (currentVersion > desiredModelVersion)
                    {
                        gonerKeys.Add((headKvp.Key == Default) ? Default : headKvp.Key);
                    }
                }
                foreach (var goner in gonerKeys)
                {
                    allHeads.Remove(goner);
                }

                // Replace 'default' with its real model number.
                if (allHeads.ContainsKey(Default))
                {
                    repo.Update(allHeads[Default].Number.LocalRevisionNumber);
                    var modelVersion = GetLiftVersionNumber(cloneLocation);
                    var fullModelVersion = "LIFT" + modelVersion;
                    if (allHeads.ContainsKey(fullModelVersion))
                    {
                        // Pick the highest revision of the two.
                        var defaultHead = allHeads[Default];
                        var otherHead = allHeads[fullModelVersion];
                        var defaultRevisionNumber = int.Parse(defaultHead.Number.LocalRevisionNumber);
                        var otherRevisionNumber = int.Parse(otherHead.Number.LocalRevisionNumber);
                        allHeads[fullModelVersion] = defaultRevisionNumber > otherRevisionNumber ? defaultHead : otherHead;
                    }
                    else
                    {
                        allHeads.Add(fullModelVersion, allHeads[Default]);
                    }
                    allHeads.Remove(Default);
                }

                // 'default' is no longer present in 'allHeads'.
                // If all of them are higher, then it is a no go.
                if (allHeads.Count == 0)
                {
                    // No useable model version, so bailout with a message to the user telling them they are 'toast'.
                    cloneResult.FinalCloneResult = FinalCloneResult.FlexVersionIsTooOld;
                    cloneResult.Message = CommonResources.kFlexUpdateRequired;
                    Directory.Delete(cloneLocation, true);
                    return;
                }

                // Now. get to the real work.
                var sortedRevisions = new SortedList<float, Revision>();
                foreach (var kvp in allHeads)
                {
                    sortedRevisions.Add(float.Parse(kvp.Key.Replace("LIFT", null)), kvp.Value);
                }
                desiredRevision = sortedRevisions.Values[sortedRevisions.Count - 1];
            }
            repo.Update(desiredRevision.Number.LocalRevisionNumber);
            cloneResult.ActualCloneFolder = cloneLocation;
            cloneResult.FinalCloneResult = FinalCloneResult.Cloned;
        }
		private void FinishCloning(Dictionary<string, string> commandLineArgs, string cloneLocation, string expectedPathToClonedRepository)
		{
			// "obtain_lift"
			//		'cloneLocation' wants to be a new folder at the $fwroot\foo\OtherRepositories\foo_LIFT folder,
			//		but Chorus may put it in $fwroot\foo\OtherRepositories\bar.
			//		So, it might need to be moved or the containing folder renamed,
			//		as we have no real control over the actual folder of 'cloneLocation' from Chorus.
			//		'expectedPathToClonedRepository' is where it is supposed to be.
			// It may not be in the right, fixed folder, so rename/move, as needed
			var actualCloneResult = new ActualCloneResult
			{
				// Be a bit pessimistic at first.
				CloneResult = null,
				ActualCloneFolder = null,
				FinalCloneResult = FinalCloneResult.ExistingCloneTargetFolder
			};

			// Update to the head of the desired branch, if possible.
			ObtainProjectStrategyLift.UpdateToTheCorrectBranchHeadIfPossible(cloneLocation, "LIFT" + commandLineArgs["-liftmodel"], actualCloneResult);

			switch (actualCloneResult.FinalCloneResult)
			{
				case FinalCloneResult.ExistingCloneTargetFolder:
					MessageBox.Show(CommonResources.kFlexProjectExists, CommonResources.kObtainProject, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
					Directory.Delete(cloneLocation, true);
					_liftFolder = null;
					return;
				case FinalCloneResult.FlexVersionIsTooOld:
					MessageBox.Show(CommonResources.kFlexUpdateRequired, CommonResources.kObtainProject, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
					Directory.Delete(cloneLocation, true);
					_liftFolder = null;
					return;
				case FinalCloneResult.Cloned:
					_gotClone = true;
					break;
			}

			if (cloneLocation == expectedPathToClonedRepository)
			{
				_liftFolder = cloneLocation;
				return;
			}

			if (!Directory.Exists(expectedPathToClonedRepository) || Utilities.FolderIsEmpty(expectedPathToClonedRepository))
			{
				if (Directory.Exists(expectedPathToClonedRepository))
					Directory.Delete(expectedPathToClonedRepository);
				DirectoryUtilities.MoveDirectorySafely(cloneLocation, expectedPathToClonedRepository);
				actualCloneResult.ActualCloneFolder = expectedPathToClonedRepository;
				actualCloneResult.FinalCloneResult = FinalCloneResult.Cloned;
				_liftFolder = expectedPathToClonedRepository;
			}
			else
			{
				// Not good at all.
				if (Directory.Exists(cloneLocation))
					Directory.Delete(cloneLocation, true);
				if (Directory.Exists(expectedPathToClonedRepository))
					Directory.Delete(expectedPathToClonedRepository, true);
				_liftFolder = null;
			}
		}
		/// <summary>
		/// Start doing whatever is needed for the supported type of action.
		/// </summary>
		public void StartWorking(Dictionary<string, string> commandLineArgs)
		{
			_baseLiftDir = Utilities.LiftOffset(Path.GetDirectoryName(commandLineArgs["-p"]));
			var fwLangProjGuid = commandLineArgs["-g"];
			var basePathForOldLiftRepos = Path.Combine(
						Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
						"LiftBridge");
			if (!Directory.Exists(basePathForOldLiftRepos))
			{
				return;
			}
			if (Directory.GetDirectories(basePathForOldLiftRepos).Length == 0)
			{
				Directory.Delete(basePathForOldLiftRepos, true);
				return;
			}
			var mappingDocPathname = Path.Combine(basePathForOldLiftRepos, MappingFilename);
			if (!File.Exists(mappingDocPathname))
			{
				return;
			}

			var mappingDoc = XDocument.Load(mappingDocPathname);
			if (!mappingDoc.Root.HasElements)
			{
				Directory.Delete(basePathForOldLiftRepos, true);
				return;
			}
			var removedElements = mappingDoc.Root.Elements(MappingTag)
				.Where(mapElement => mapElement.Attribute(ProjectguidAttrTag) == null || mapElement.Attribute(RepositoryidentifierAttrTag) == null).ToList();
			foreach (var goner in removedElements)
			{
				goner.Remove();
			}
			if (removedElements.Count > 0)
			{
				removedElements.Clear();
				mappingDoc.Save(mappingDocPathname);
			}

			string oldLiftFolder = null;
			foreach (var mapElement in mappingDoc.Root.Elements(MappingTag).ToList())
			{
				if (mapElement.Attribute(ProjectguidAttrTag).Value.ToLowerInvariant() != fwLangProjGuid.ToLowerInvariant())
					continue;

				var repoId = mapElement.Attribute(RepositoryidentifierAttrTag).Value;

				foreach (var directory in Directory.GetDirectories(basePathForOldLiftRepos).Where(directory => Directory.Exists(Path.Combine(directory, Utilities.hg))))
				{
					var repo = new HgRepository(directory, new NullProgress());
					if (repo.Identifier != repoId)
						continue;

					oldLiftFolder = directory;
					break;
				}
				if (oldLiftFolder == null)
					continue;

				RemoveElementAndSaveDoc(mappingDoc, mapElement, mappingDocPathname);
				break;
			}
			if (oldLiftFolder == null)
				return;

			var actualCloneResult = new ActualCloneResult();
			ObtainProjectStrategyLift.MakeLocalClone(oldLiftFolder, _baseLiftDir);
			actualCloneResult.ActualCloneFolder = _baseLiftDir;
			actualCloneResult.FinalCloneResult = FinalCloneResult.Cloned;

			// Update to the head of the desired branch, if possible.
			ObtainProjectStrategyLift.UpdateToTheCorrectBranchHeadIfPossible(_baseLiftDir, "LIFT" + commandLineArgs["-liftmodel"], actualCloneResult);
			if(actualCloneResult.FinalCloneResult != FinalCloneResult.Cloned)
			{
				MessageBox.Show(actualCloneResult.Message, LocalizationManager.GetString("LiftBridge_MoveFailed_Title",
																												 "Failed to update LiftBridge project.",
																												 "Title of error message shown when moving a LiftBridge repo to the FlexBridge location fails."));
				// The clone and update did not go smoothly.
				return;
			}
			var folderToZap = mappingDoc.Root.HasElements || Directory.GetDirectories(basePathForOldLiftRepos).Length > 1
								  ? oldLiftFolder
								  : basePathForOldLiftRepos;
			Directory.Delete(folderToZap, true);
			var otherRepoDir = Directory.GetParent(_baseLiftDir).FullName;
			if (!Directory.Exists(_baseLiftDir) && Directory.GetDirectories(_baseLiftDir).Length == 0)
				Directory.Delete(otherRepoDir);
		}