Skip to content

Commit

Permalink
Allow Restore to discard pending changes (#6330)
Browse files Browse the repository at this point in the history
* allow restoring of a tag when changes have already been made
* add test that checks whether restoring different tag for same assets will discard pending changes

Co-authored-by: Ben Broderick Phillips <[email protected]>
  • Loading branch information
scbedd and benbp authored Jun 14, 2023
1 parent d156b3e commit fe71549
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,78 @@ public async Task InvalidTagThrows(string inputJson, string httpException)
}
}

[EnvironmentConditionalSkipTheory]
[InlineData(
@"{
""AssetsRepo"": ""Azure/azure-sdk-assets-integration"",
""AssetsRepoPrefixPath"": ""pull/scenarios"",
""AssetsRepoId"": """",
""TagPrefix"": ""main"",
""Tag"": ""python/tables_9e81fb""
}")]
[Trait("Category", "Integration")]
public async Task VerifyRestoreDiscardsChanges(string inputJson)
{
var folderStructure = new string[]
{
GitStoretests.AssetsJson
};

Assets assets = JsonSerializer.Deserialize<Assets>(inputJson);
var testFolder = TestHelpers.DescribeTestFolder(assets, folderStructure);
try
{
var jsonFileLocation = Path.Join(testFolder, GitStoretests.AssetsJson);

var parsedConfiguration = await _defaultStore.ParseConfigurationFile(jsonFileLocation);
await _defaultStore.Restore(jsonFileLocation);

// Calling Path.GetFullPath of the Path.Combine will ensure any directory separators are normalized for
// the OS the test is running on. The reason being is that AssetsRepoPrefixPath, if there's a separator,
// will be a forward one as expected by git but on Windows this won't result in a usable path.
string localFilePath = Path.GetFullPath(Path.Combine(parsedConfiguration.AssetsRepoLocation.ToString(), parsedConfiguration.AssetsRepoPrefixPath.ToString()));

// Verify files from Tag
Assert.Equal(4, System.IO.Directory.EnumerateFiles(localFilePath).Count());
Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 1));
Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file2.txt", 2));
Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 2));
Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file4.txt", 1));

// Delete a couple of files
File.Delete(Path.Combine(localFilePath, "file2.txt"));
File.Delete(Path.Combine(localFilePath, "file4.txt"));

// Add a file
TestHelpers.CreateFileWithInitialVersion(localFilePath, "file5.txt");

// Verify the set of files after the additions/deletions
Assert.Equal(3, System.IO.Directory.EnumerateFiles(localFilePath).Count());
Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 1));
Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 2));
Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file5.txt", 1));

// simulate a feature branch checkout in the langauge repo. change the targeted
// tag in place. The changes from lines above should be automatically discarded.
var existingAssets = TestHelpers.LoadAssetsFromFile(jsonFileLocation);
existingAssets.Tag = "python/tables_fc54d0";
TestHelpers.UpdateAssetsFile(existingAssets, jsonFileLocation);

await _defaultStore.Restore(jsonFileLocation);

// Verify the only files there are ones from the Tag
Assert.Equal(3, System.IO.Directory.EnumerateFiles(localFilePath).Count());
Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 1));
Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file2.txt", 1));
Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 1));
await TestHelpers.CheckBreadcrumbAgainstAssetsJsons(new string[] { jsonFileLocation });
}
finally
{
DirectoryHelper.DeleteGitDirectory(testFolder);
}
}

[EnvironmentConditionalSkipTheory]
[InlineData(
@"{
Expand Down
42 changes: 27 additions & 15 deletions tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/GitStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ public async Task<string> Restore(string pathToAssetsJson) {
InitializeAssetsRepo(config);
}

CheckoutRepoAtConfig(config);
CheckoutRepoAtConfig(config, cleanEnabled: true);
await BreadCrumb.Update(config);

return config.AssetsRepoLocation.ToString();
Expand Down Expand Up @@ -214,27 +214,31 @@ public async Task Reset(string pathToAssetsJson)

if (allowReset)
{
try
{
GitHandler.Run("checkout *", config);
GitHandler.Run("clean -xdf", config);
}
catch(GitProcessException e)
{
HideOrigin(config);
throw GenerateInvokeException(e.Result);
}

if (!string.IsNullOrWhiteSpace(config.Tag))
{
CheckoutRepoAtConfig(config);
Clean(config);
CheckoutRepoAtConfig(config, cleanEnabled: false);
await BreadCrumb.Update(config);
}
}

HideOrigin(config);
}

private void Clean(GitAssetsConfiguration config)
{
try
{
GitHandler.Run("checkout *", config);
GitHandler.Run("clean -xdf", config);
}
catch (GitProcessException e)
{
HideOrigin(config);
throw GenerateInvokeException(e.Result);
}
}

/// <summary>
/// Given a CommandResult, generate an HttpException.
/// </summary>
Expand Down Expand Up @@ -297,12 +301,20 @@ private void HideOrigin(GitAssetsConfiguration config)
/// Given a configuration, set the sparse-checkout directory for the config, then attempt checkout of the targeted Tag.
/// </summary>
/// <param name="config"></param>
public void CheckoutRepoAtConfig(GitAssetsConfiguration config)
/// <param name="cleanEnabled">A newly initialized repo should not be 'cleaned', as that will result in a git error. However, a new
/// clone looks the same as being on the wrong tag. This variable allows us to prevent over-active cleaning that would result in exceptions.</param>
public void CheckoutRepoAtConfig(GitAssetsConfiguration config, bool cleanEnabled = true)
{
// we are already on a targeted tag and as such don't want to discard our recordings
if (Assets.TryGetValue(config.AssetsJsonRelativeLocation.ToString(), out var value) && value == config.Tag)
{
return;
}
// if we are NOT on our targeted tag, before we attempt to switch we need to reset without asking for permission
else if (cleanEnabled)
{
Clean(config);
}

var checkoutPaths = ResolveCheckoutPaths(config);

Expand Down Expand Up @@ -466,7 +478,7 @@ public bool InitializeAssetsRepo(GitAssetsConfiguration config, bool forceInit =
throw GenerateInvokeException(e.Result);
}

CheckoutRepoAtConfig(config);
CheckoutRepoAtConfig(config, cleanEnabled: false);
workCompleted = true;
}

Expand Down

0 comments on commit fe71549

Please sign in to comment.