using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Perforce.P4 { /// /// Describes the mapping type. /// public enum MapType { None, Include, Exclude, Overlay, Share, Isolate, Import, StreamPathExclude } /// /// A single entry in a view map. /// public class MapEntry { public MapEntry(MapType type, PathSpec left, PathSpec right) { Type = type; Left = left; Right = right; } public MapType Type { get; set; } public PathSpec Left { get; set; } public PathSpec Right { get; set; } public override bool Equals(object obj) { if (obj is MapEntry) { MapEntry o = obj as MapEntry; if (o.Right != null) { return ((this.Type == o.Type) && (this.Left.Equals(o.Left)) && (this.Right.Equals(o.Right))); } else { return ((this.Type == o.Type) && (this.Left.Equals(o.Left))); } } return false; } } /// /// Maps one or more Perforce file specs to zero, one, or more /// other Perforce file specs. /// public class ViewMap : List { /// /// Create an empty workspace view /// /// public ViewMap() { } /// /// Create a workspace view /// /// List of Left/Right pairs for the map public ViewMap(List text) { foreach (string line in text) { Add(line); } } /// /// Create a workspace view /// /// Array of Left/Right pairs for the map public ViewMap(string[] text) { foreach (string line in text) { Add(line); } } /// /// Split a single line from a view specification into left and right parts /// /// /// Handles case where the left and/or the right string are enclosed /// in quotes because they contain spaces. I.e "C:\my code\project 1\..." /// /// /// public static String[] SplitViewLine(String line) { //Get rid of leading/trailing white spaces line = line.Trim(); String[] parts = new String[2]; int idx =0; int start=0; int cnt=0; //Determine if this is a Stream path and remove the path type if (line.StartsWith("share") || line.StartsWith("isolate") || line.StartsWith("import") || line.StartsWith("exclude")) { line=line.Remove(0,line.IndexOf(" ")+1); String[] streamLine = line.Split(' '); if (streamLine.Length==1) { line = streamLine[0]; } } if (line.Length > 0) { if (line[idx] == '"') { //Left side is quoted, skip to the next quote start = ++idx; while (idx < line.Length && line[idx] != '"') { idx++; cnt = idx - start; } } else { if (line.Contains(' ') == false) { parts[0] = line; parts[1] = string.Empty; return parts; } { // not quoted, so skip to the next white space start = idx; while (!Char.IsWhiteSpace(line[idx])) { idx++; cnt = idx - start; } } } } parts[0] = line.Substring(start, cnt).TrimStart('-','+'); if (line.Length > 0) { // skip the separating white spaces while (Char.IsWhiteSpace(line[idx])) idx++; // rest (trimmed of quotes if any) of line is the right value parts[1] = line.Substring(idx).Trim('"', ' '); } return parts; } /// /// Add a line to the end of the view /// /// Left/Right pair for the map public void Add(String line) { MapType lineType = MapType.Include; if (line.Length > 0) { if ((line[0] == '-') || (line.StartsWith("\"-"))) { lineType = MapType.Exclude; } else if ((line[0] == '+') || (line.StartsWith("\"+"))) { lineType = MapType.Overlay; } else if (line.StartsWith("share")) { lineType = MapType.Share; } else if (line.StartsWith("isolate")) { lineType = MapType.Isolate; } else if (line.StartsWith("import")) { lineType = MapType.Import; } else if (line.StartsWith("exclude")) { lineType = MapType.StreamPathExclude; } } String[] sides = SplitViewLine(line.ToString()); Add(sides[0], sides[1], lineType); } /// /// Add a line to the end of the view /// /// left side of mapping /// right side of mapping /// public void Add(String left, String right, MapType lineType) { MapEntry entry = new MapEntry( lineType, new DepotPath(left), new ClientPath(right)); Add(entry); } /// /// Convert to a Perforce server compatible string for a workspace spec /// /// public override String ToString() { String value = String.Empty; string right; for (int idx = 0; idx < Count; idx++) { MapEntry entry = this[idx]; string left = entry.Left.Path; if (entry.Type == MapType.Exclude) { if (left.Contains(' ')) { left = String.Format("\"-{0}\"", left); } else left = String.Format("-{0}", left); } else if (entry.Type == MapType.Overlay) { if (left.Contains(' ')) { left = String.Format("\"+{0}\"", left); } else left = String.Format("+{0}", left); } else if (entry.Type == MapType.Share) { if (left.Contains(' ')) { left = String.Format("share \"{0}\"", left); } else left = String.Format("share {0}", left); } else if (entry.Type == MapType.Isolate) { if (left.Contains(' ')) { left = String.Format("isolate \"{0}\"", left); } else left = String.Format("isolate {0}", left); } else if (entry.Type == MapType.Import) { if (left.Contains(' ')) { left = String.Format("import \"{0}\"", left); } else left = String.Format("import {0}", left); } else if (entry.Type == MapType.StreamPathExclude) { if (left.Contains(' ')) { left = String.Format("exclude \"{0}\"", left); } else left = String.Format("exclude {0}", left); } else if (entry.Type == MapType.Include||entry.Type==MapType.None) { if (left.Contains(' ')) { left = String.Format("\"{0}\"", left); } else left = String.Format("{0}", left); } try { right = entry.Right.Path; if (right.Contains(' ')) { right = String.Format("\"{0}\"", right); } } catch { right = string.Empty; } value += String.Format("{0} {1}\r\n", left, right); } return value; } } }