/******************************************************************************* Copyright (c) 2011, Perforce Software, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ /******************************************************************************* * Name : BranchSpec.cs * * Author : wjb * * Description : Class used to abstract a branch specification in Perforce. * ******************************************************************************/ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Perforce.P4 { /// ///
p4 help branch ///
///
branch -- Create, modify, or delete a branch view specification ///
///
p4 branch [-f] name ///
p4 branch -d [-f] name ///
p4 branch [ -S stream ] [ -P parent ] -o name ///
p4 branch -i [-f] ///
///
A branch specification ('spec') is a named, user-defined mapping of ///
depot files to depot files. It can be used with most of the commands ///
that operate on two sets of files ('copy', 'merge', 'integrate', ///
'diff2', etc.) ///
///
Creating a branch spec does not branch files. To branch files, use ///
'p4 copy', with or without a branch spec. ///
///
The 'branch' command puts the branch spec into a temporary file and ///
invokes the editor configured by the environment variable $P4EDITOR. ///
Saving the file creates or modifies the branch spec. ///
///
The branch spec contains the following fields: ///
///
Branch: The branch spec name (read only). ///
///
Owner: The user who created this branch spec. Can be changed. ///
///
Update: The date this branch spec was last modified. ///
///
Access: The date of the last command used with this spec. ///
///
Description: A description of the branch spec (optional). ///
///
Options: Flags to change the branch spec behavior. The defaults ///
are marked with *. ///
///
locked Permits only the owner to change the spec. ///
unlocked * Prevents the branch spec from being deleted. ///
///
View: Lines mapping of one view of depot files to another. ///
Both the left and right-hand sides of the mappings refer ///
to the depot namespace. See 'p4 help views' for more on ///
view syntax. ///
///
New branch specs are created with a default view that maps all depot ///
files to themselves. This view must be changed before the branch ///
spec can be saved. ///
///
The -d flag deletes the named branch spec. ///
///
The -o flag writes the branch spec to standard output. The user's ///
editor is not invoked. ///
///
The -i flag causes a branch spec to be read from the standard input. ///
The user's editor is not invoked. ///
///
The -f flag enables a user with 'admin' privilege to delete the spec ///
or set the 'last modified' date. By default, specs can be deleted ///
only by their owner. ///
///
A branch spec can also be used to expose the internally generated ///
mapping of a stream to its parent. (See 'p4 help stream' and 'p4 ///
help streamintro'.) ///
///
The -S stream flag will expose the internally generated mapping. ///
The -P flag may be used with -S to treat the stream as if it were a ///
child of a different parent. The -o flag is required with -S. ///
///
///
/// /// A branch view specification in a Perforce repository. /// public class BranchSpec { /// /// A branch view specification in a Perforce repository. /// public BranchSpec() { } /// /// A branch view specification in a Perforce repository. /// /// The date of the last command used with this spec. /// A description of the branch spec (optional). /// The branch spec name (read only). /// When true, permits only the owner to change the spec. /// Flags to change the branch spec behavior. /// The user who created this branch spec. /// Specifies structural and semantic metadata for form types. /// The date this branch spec was last modified. /// Lines mapping of one view of depot files to another. public BranchSpec(string id, string owner, DateTime updated, DateTime accessed, string description, bool locked, ViewMap viewmap, FormSpec spec, string options ) { Id = id; Owner = owner; Updated = updated; Accessed = accessed; Description = description; Locked = locked; ViewMap = viewmap; Spec = spec; Options = options; } private bool _initialized; private FormBase _baseForm; #region properties /// /// The branch spec name (read only). /// public string Id { get; set; } /// /// The user who created this branch spec. Can be changed. /// public string Owner { get; set; } /// /// The date this branch spec was last modified. /// public DateTime Updated { get; set; } /// /// The date of the last command used with this spec. /// public DateTime Accessed { get; set; } /// /// A description of the branch spec (optional). /// public string Description { get; set; } /// /// When true, permits only the owner to change the spec. /// public bool Locked { get; set; } /// /// Lines mapping of one view of depot files to another. /// public ViewMap ViewMap { get; set; } /// /// Specifies structural and semantic metadata for form types. /// public FormSpec Spec { get; set; } /// /// Flags to change the branch spec behavior. /// [Obsolete("Use Locked Property")] public string Options { get { return Locked?"locked":string.Empty; } set { Locked = (value == "locked"); } } #endregion #region fromTaggedOutput /// /// Read the fields from the tagged output of a branch command /// /// Tagged output from the 'branch' command public void FromBranchSpecCmdTaggedOutput(TaggedObject objectInfo) { _initialized = true; _baseForm = new FormBase(); _baseForm.SetValues(objectInfo); if (objectInfo.ContainsKey("Branch")) Id = objectInfo["Branch"]; if (objectInfo.ContainsKey("Owner")) Owner = objectInfo["Owner"]; if (objectInfo.ContainsKey("Update")) { DateTime v = DateTime.MinValue; DateTime.TryParse(objectInfo["Update"], out v); Updated = v; } if (objectInfo.ContainsKey("Access")) { DateTime v = DateTime.MinValue; DateTime.TryParse(objectInfo["Access"], out v); Accessed = v; } if (objectInfo.ContainsKey("Description")) Description = objectInfo["Description"]; if (objectInfo.ContainsKey("Options")) { if(objectInfo["Options"] == "locked") Locked = true; } else Locked = false; int idx = 0; string key = String.Format("View{0}", idx); if (objectInfo.ContainsKey(key)) { ViewMap = new ViewMap(); while (objectInfo.ContainsKey(key)) { ViewMap.Add(objectInfo[key]); idx++; key = String.Format("View{0}", idx); } } else { ViewMap = null; } } #endregion #region client spec support /// /// Parse the fields from a branch specification /// /// Text of the branch specification in server format /// public bool Parse(String spec) { _baseForm = new FormBase(); _baseForm.Parse(spec); // parse the values into the underlying dictionary if (_baseForm.ContainsKey("Branch")) { Id = _baseForm["Branch"] as string; } if (_baseForm.ContainsKey("Owner")) { Owner = _baseForm["Owner"] as string; } if (_baseForm.ContainsKey("Update")) { DateTime v = DateTime.MinValue; DateTime.TryParse(_baseForm["Update"] as string, out v); Updated = v; } if (_baseForm.ContainsKey("Access")) { DateTime v = DateTime.MinValue; DateTime.TryParse(_baseForm["Access"] as string, out v); Accessed = v; } if (_baseForm.ContainsKey("Description")) { Description = _baseForm["Description"] as string; } if (_baseForm.ContainsKey("Options")) { Options = _baseForm["Options"] as string; } if ((_baseForm.ContainsKey("View")) && (_baseForm["View"] is IList)) { IList lines = _baseForm["View"] as IList; ViewMap = new ViewMap(lines.ToArray()); } return true; } /// /// Format of a branch specification used to save a branch to the server /// private static String BranchSpecFormat = "Branch:\t{0}\r\n" + "\r\n" + "Update:\t{1}\r\n" + "\r\n" + "Access:\t{2}\r\n" + "\r\n" + "Owner:\r\n\t{3}\r\n" + "\r\n" + "Description:\r\n\t{4}\r\n" + "\r\n" + "Options:\t{5}\r\n" + "\r\n" + "View:\r\n\t{6}\r\n"; /// /// Convert to specification in server format /// /// override public String ToString() { String viewStr = String.Empty; if (ViewMap != null) viewStr = ViewMap.ToString().Replace("\r\n", "\r\n\t").Trim(); String OptionsStr = string.Empty; if (Locked) { OptionsStr = "locked"; } else { OptionsStr = "unlocked"; } String value = String.Format(BranchSpecFormat, Id, FormBase.FormatDateTime(Updated), FormBase.FormatDateTime(Accessed), Owner, Description, OptionsStr, viewStr); return value; } #endregion /// /// Read the fields from the tagged output of a branches command /// /// Tagged output from the 'branches' command public void FromBranchSpecsCmdTaggedOutput(TaggedObject objectInfo, string offset, bool dst_mismatch) { _initialized = true; _baseForm = new FormBase(); _baseForm.SetValues(objectInfo); if (objectInfo.ContainsKey("branch")) Id = objectInfo["branch"]; if (objectInfo.ContainsKey("Owner")) Owner = objectInfo["Owner"]; if (objectInfo.ContainsKey("Access")) { DateTime UTC = FormBase.ConvertUnixTime(objectInfo["Access"]); DateTime GMT = new DateTime(UTC.Year, UTC.Month, UTC.Day, UTC.Hour, UTC.Minute, UTC.Second, DateTimeKind.Unspecified); Accessed = FormBase.ConvertFromUTC(GMT, offset, dst_mismatch); } if (objectInfo.ContainsKey("Update")) { DateTime UTC = FormBase.ConvertUnixTime(objectInfo["Update"]); DateTime GMT = new DateTime(UTC.Year, UTC.Month, UTC.Day, UTC.Hour, UTC.Minute, UTC.Second, DateTimeKind.Unspecified); Updated = FormBase.ConvertFromUTC(GMT, offset, dst_mismatch); } if (objectInfo.ContainsKey("Options")) { if (objectInfo["Options"] == "locked") Locked = true; } else Locked = false; if (objectInfo.ContainsKey("Description")) Description = objectInfo["Description"]; } } }