Example #1
0
        private TeeWorkspace MatchExactWorkspace(TeeWorkspace[] teeWorkspaces, string name, TfsVCTeeWorkspaceMapping[] definitionMappings, string sourcesDirectory)
        {
            ArgUtil.NotNullOrEmpty(name, nameof(name));
            ArgUtil.NotNullOrEmpty(sourcesDirectory, nameof(sourcesDirectory));

            // Short-circuit early if the sources directory is empty.
            //
            // Consider the sources directory to be empty if it only contains a .tf directory exists. This can
            // indicate the workspace is in a corrupted state and the tf commands (e.g. status) will not return
            // reliable information. An easy way to reproduce this is to delete the workspace directory, then
            // run "tf status" on that workspace. The .tf directory will be recreated but the contents will be
            // in a corrupted state.
            if (!Directory.Exists(sourcesDirectory) ||
                !Directory.EnumerateFileSystemEntries(sourcesDirectory).Any(x => !x.EndsWith($"{Path.DirectorySeparatorChar}.tf")))
            {
                Trace.Info($"Sources directory does not exist or is empty.");
                return(null);
            }

            string machineName = Environment.MachineName;

            Trace.Info("Attempting to find a matching workspace.");
            Trace.Info($"Expected workspace name '{name}', machine name '{machineName}', number of mappings '{definitionMappings?.Length ?? 0}'.");
            foreach (TeeWorkspace teeWorkspace in teeWorkspaces ?? new TeeWorkspace[0])
            {
                // Compare the works name, machine name, and number of mappings.
                Trace.Info($"Candidate workspace name '{teeWorkspace.Name}', machine name '{teeWorkspace.Computer}', number of mappings '{teeWorkspace.Mappings?.Length ?? 0}'.");
                if (!string.Equals(teeWorkspace.Name, name, StringComparison.Ordinal) ||
                    !string.Equals(teeWorkspace.Computer, machineName, StringComparison.Ordinal) ||
                    (teeWorkspace.Mappings?.Length ?? 0) != (definitionMappings?.Length ?? 0))
                {
                    continue;
                }

                // TODO: Is there such a thing as a single level cloak?
                // Sort the TEE mappings.
                List <TeeMapping> sortedTeeMappings =
                    (teeWorkspace.Mappings ?? new TeeMapping[0])
                    .OrderBy(x => !x.Cloak)    // Cloaks first
                    .ThenBy(x => !x.Recursive) // Then recursive maps
                    .ThenBy(x => x.ServerPath) // Then sort by server path
                    .ToList();
                sortedTeeMappings.ForEach(x => Trace.Info($"TEE mapping: cloak '{x.Cloak}', recursive '{x.Recursive}', server path '{x.ServerPath}', local path '{x.LocalPath}'."));

                // Sort the definition mappings.
                List <TfsVCTeeWorkspaceMapping> sortedDefinitionMappings =
                    (definitionMappings ?? new TfsVCTeeWorkspaceMapping[0])
                    .OrderBy(x => x.MappingType != TfsVCTeeMappingType.Cloak) // Cloaks first
                    .ThenBy(x => !RecursiveServerPath(x.ServerPath))          // Then recursive maps
                    .ThenBy(x => NormalizeServerPath(x.ServerPath))           // Then sort by the normalized server path
                    .ToList();
                sortedDefinitionMappings.ForEach(x => Trace.Info($"Definition mapping: cloak '{x.MappingType == TfsVCTeeMappingType.Cloak}', recursive '{RecursiveServerPath(x.ServerPath)}', server path '{NormalizeServerPath(x.ServerPath)}', local path '{ResolveMappingLocalPath(x, sourcesDirectory)}'."));

                // Compare the mappings,
                bool allMatch = true;
                for (int i = 0; i < sortedTeeMappings.Count; i++)
                {
                    TeeMapping teeMapping = sortedTeeMappings[i];
                    TfsVCTeeWorkspaceMapping definitionMapping = sortedDefinitionMappings[i];
                    if (teeMapping.Cloak)
                    {
                        // The TEE mapping is a cloak.

                        // Verify the definition mapping is a cloak and the server paths match.
                        if (definitionMapping.MappingType != TfsVCTeeMappingType.Cloak ||
                            !string.Equals(teeMapping.ServerPath, definitionMapping.ServerPath, StringComparison.Ordinal))
                        {
                            allMatch = false; // Mapping comparison failed.
                            break;
                        }
                    }
                    else
                    {
                        // The TEE mapping is a map.

                        // Verify the definition mapping is a map and the local paths match.
                        if (definitionMapping.MappingType != TfsVCTeeMappingType.Map ||
                            !string.Equals(teeMapping.LocalPath, ResolveMappingLocalPath(definitionMapping, sourcesDirectory), StringComparison.Ordinal))
                        {
                            allMatch = false; // Mapping comparison failed.
                            break;
                        }

                        if (teeMapping.Recursive)
                        {
                            // The TEE mapping is a recursive map.

                            // Verify the server paths match.
                            if (!string.Equals(teeMapping.ServerPath, definitionMapping.ServerPath, StringComparison.Ordinal))
                            {
                                allMatch = false; // Mapping comparison failed.
                                break;
                            }
                        }
                        else
                        {
                            // The TEE mapping is a single-level map.

                            // Verify the definition mapping is a single-level map and the normalized server paths match.
                            if (RecursiveServerPath(definitionMapping.ServerPath) ||
                                !string.Equals(teeMapping.ServerPath, NormalizeServerPath(definitionMapping.ServerPath), StringComparison.Ordinal))
                            {
                                allMatch = false; // Mapping comparison failed.
                                break;
                            }
                        }
                    }
                }

                if (allMatch)
                {
                    Trace.Info("Matching workspace found.");
                    return(teeWorkspace);
                }
            }

            Trace.Info("Matching workspace not found.");
            return(null);
        }
Example #2
0
 private static string ResolveMappingLocalPath(TfsVCTeeWorkspaceMapping definitionMapping, string sourcesDirectory)
 {
     return(Path.Combine(
                sourcesDirectory,
                (definitionMapping.LocalPath ?? string.Empty).Trim('/', '\\').Replace('\\', Path.DirectorySeparatorChar)));
 }