private static string CreateCachedRepo(string source, string commitId, IDictionary <string, string> environments) { string cachedPath = null; if (source.IndexOf("github.com", StringComparison.OrdinalIgnoreCase) != -1) { // If we're allowed to cache the repository, check if it already exists. If not clone it. string repoName = Path.GetFileNameWithoutExtension(source.Split('/').Last()); cachedPath = Path.Combine(PathHelper.RepositoryCachePath, repoName); // Check for the actually .git folder, in case some bogus parent exists but is not an actual repo bool alreadyExists = Directory.Exists(Path.Combine(cachedPath, ".git")) && IsGitRepo(cachedPath); Executable gitExe = GetGitExe(cachedPath, environments); if (alreadyExists) { TestTracer.Trace("Using cached copy at location {0}", cachedPath); // Get it into a clean state on the correct commit id try { // If we don't have a specific commit id to go to, use origin/master if (commitId == null) { commitId = "origin/master"; } GitExecute(gitExe, "reset --hard " + commitId); } catch (Exception e) { // Some repos like Drupal don't use a master branch (e.g. default branch is 7.x). In those cases, // simply reset to the HEAD. That won't undo any test commits, but at least it does some cleanup. if (e.Message.Contains("ambiguous argument 'origin/master'")) { GitExecute(gitExe, "reset --hard HEAD"); } else if (e.Message.Contains("unknown revision")) { // If that commit id doesn't exist, try fetching and doing the reset again // The reason we don't initially fetch is to avoid the network hit when not necessary GitExecute(gitExe, "fetch origin"); GitExecute(gitExe, "reset --hard " + commitId); } else { throw; } } GitExecute(gitExe, "clean -dxf"); } else { // Delete any leftover, ignoring errors FileSystemHelpers.DeleteDirectorySafe(cachedPath); TestTracer.Trace("Could not find a cached copy at {0}. Cloning from source {1}.", cachedPath, source); PathHelper.EnsureDirectory(cachedPath); GitExecute(gitExe, "clone \"{0}\" .", source); // If we have a commit id, reset to it in case it's older than the latest on our clone if (commitId != null) { GitExecute(gitExe, "reset --hard " + commitId); } } } return(cachedPath); }