using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace Perforce.P4 { /// /// Represents a Perforce server and connection. /// public partial class Repository : IDisposable { /// /// Create a repository on the specified server. /// /// The repository server./// public Repository (Server server) { Server = server; } public Server Server {get; private set;} private Connection _connection; public Connection Connection { get { if (_connection == null) { _connection = new Connection(Server); } return _connection; } } /// /// Return a list of FileSpecs of files in the depot that correspond /// to the passed-in FileSpecs. /// /// /// /// /// ///
p4 help files ///
///
files -- List files in the depot ///
///
p4 files [ -a ] [ -A ] [ -m max ] file[revRange] ... ///
///
List details about specified files: depot file name, revision, ///
file, type, change action and changelist number of the current ///
head revision. If client syntax is used to specify the file ///
argument, the client view mapping is used to determine the ///
corresponding depot files. ///
///
By default, the head revision is listed. If the file argument ///
specifies a revision, then all files at that revision are listed. ///
If the file argument specifies a revision range, the highest revision ///
in the range is used for each file. For details about specifying ///
revisions, see 'p4 help revisions'. ///
///
The -a flag displays all revisions within the specific range, rather ///
than just the highest revision in the range. ///
///
The -A flag displays files in archive depots. ///
///
The -m flag limits files to the first 'max' number of files. ///
///
///
/// /// To get a maximum of 10 files from the repository: /// /// /// Options opts = new Options(GetFilesCmdFlags.None, 10); /// FileSpec fs = new FileSpec(new DepotPath("//depot/..."), null); /// List lfs = new List(); /// lfs.Add(fs); /// IList<FileSpec> files = _repository.getDepotFiles(lfs, opts); /// /// /// /// public IList GetDepotFiles(IList filespecs, Options options) { P4.P4Command filesCmd = new P4Command(this, "files", true, FileSpec.ToStrings(filespecs)); P4.P4CommandResult r = filesCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } List value = new List(); foreach (P4.TaggedObject obj in r.TaggedOutput) { string path = obj["depotFile"]; PathSpec ps = new DepotPath(path); int rev = 0; int.TryParse(obj["rev"], out rev); FileSpec fs = new FileSpec(ps, new Revision(rev)); value.Add(fs); } return value; } /// /// Return a list of FileSpecs of files opened for specified changelists. /// /// /// /// /// ///
p4 help opened ///
///
opened -- List open files and display file status ///
///
p4 opened [-a -c changelist# -C client -u user -m max] [file ...] ///
///
Lists files currently opened in pending changelists, or, for ///
specified files, show whether they are currently opened or locked. ///
If the file specification is omitted, all files open in the current ///
client workspace are listed. ///
///
The -a flag lists opened files in all clients. By default, only ///
files opened by the current client are listed. ///
///
The -c changelist# flag lists files opened in the specified ///
changelist#. ///
///
The -C client flag lists files open in the specified client workspace. ///
///
The -u user flag lists files opened by the specified user. ///
///
The -m max flag limits output to the first 'max' number of files. ///
///
///
public IList GetOpenedFiles(IList filespecs, Options options) { P4.P4Command openedCmd = new P4Command(this, "opened", true, FileSpec.ToStrings(filespecs)); P4.P4CommandResult r = openedCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } List value = new List(); DepotPath dps = null; ClientPath cps = null; int revision = 0; Revision rev = new Revision(0); Revision haveRev = new Revision(0); StringEnum action = null; int change = -1; FileType type = null; DateTime submittime = DateTime.MinValue; string user = string.Empty; string client = string.Empty; foreach (P4.TaggedObject obj in r.TaggedOutput) { if (obj.ContainsKey("depotFile")) { dps = new DepotPath(obj["depotFile"]); } if (obj.ContainsKey("clientFile")) { cps = new ClientPath(obj["clientFile"]); } if (obj.ContainsKey("rev")) { int.TryParse(obj["rev"], out revision); rev = new Revision(revision); } if (obj.ContainsKey("haveRev")) { int.TryParse(obj["haveRev"], out revision); haveRev = new Revision(revision); } if (obj.ContainsKey("action")) { action = obj["action"]; } if (obj.ContainsKey("change")) { int.TryParse(obj["change"], out change); } if (obj.ContainsKey("type")) { type = new FileType(obj["type"]); } if (obj.ContainsKey("user")) { user = obj["user"]; } if (obj.ContainsKey("client")) { client = obj["client"]; } File f = new File(dps, cps, rev, haveRev, change, action, type, submittime, user, client); value.Add(f); } return value; } /// /// Use the p4 fstat command to get the file metadata for the files /// matching the FileSpec. /// /// /// /// /// ///
p4 help fstat ///
///
fstat -- Dump file info ///
///
p4 fstat [-F filter -L -T fields -m max -r] [-c | -e changelist#] ///
[-Ox -Rx -Sx] file[rev] ... ///
///
Fstat lists information about files, one line per file. Fstat is ///
intended for use in Perforce API applications, where the output can ///
be accessed as variables, but its output is also suitable for parsing ///
from the client command output in scripts. ///
///
The fields that fstat displays are: ///
///
clientFile -- local path (host or Perforce syntax) ///
depotFile -- name in depot ///
movedFile -- name in depot of moved to/from file ///
path -- local path (host syntax) ///
isMapped -- set if mapped client file is synced ///
shelved -- set if file is shelved ///
headAction -- action at head rev, if in depot ///
headChange -- head rev changelist#, if in depot ///
headRev -- head rev #, if in depot ///
headType -- head rev type, if in depot ///
headTime -- head rev changelist time, if in depot ///
headModTime -- head rev mod time, if in depot ///
movedRev -- head rev # of moved file ///
haveRev -- rev had on client, if on client ///
desc -- change description ///
digest -- MD5 digest (fingerprint) ///
fileSize -- file size ///
action -- open action, if opened ///
type -- open type, if opened ///
actionOwner -- user who opened file, if opened ///
change -- open changelist#, if opened ///
resolved -- resolved integration records ///
unresolved -- unresolved integration records ///
reresolvable -- reresolvable integration records ///
otherOpen -- set if someone else has it open ///
otherOpen# -- list of user@client with file opened ///
otherLock -- set if someone else has it locked ///
otherLock# -- user@client with file locked ///
otherAction# -- open action, if opened by someone else ///
otherChange# -- changelist, if opened by someone else ///
ourLock -- set if this user/client has it locked ///
resolveAction# -- pending integration record action ///
resolveBaseFile# -- pending integration base file ///
resolveBaseRev# -- pending integration base rev ///
resolveFromFile# -- pending integration from file ///
resolveStartFromRev# -- pending integration from start rev ///
resolveEndFromRev# -- pending integration from end rev ///
///
The -F flag lists only files satisfying the filter expression. This ///
filter syntax is similar to the one used for 'jobs -e jobview' and is ///
used to evaluate the contents of the fields in the preceding list. ///
Filtering is case-sensitive. ///
///
Example: -Ol -F "fileSize > 1000000 & headType=text" ///
///
Note: filtering is not optimized with indexes for performance. ///
///
The -L flag can be used with multiple file arguments that are in ///
full depot syntax and include a valid revision number. When this ///
flag is used the arguments are processed together by building an ///
internal table similar to a label. This file list processing is ///
significantly faster than having to call the internal query engine ///
for each individual file argument. However, the file argument syntax ///
is strict and the command will not run if an error is encountered. ///
///
The -T fields flag returns only the specified fields. The field names ///
can be specified using a comma- or space-delimited list. ///
///
Example: -Ol -T "depotFile, fileSize" ///
///
The -m max flag limits output to the specified number of files. ///
///
The -r flag sorts the output in reverse order. ///
///
The -c changelist# flag displays files modified after the specified ///
changelist was submitted. This operation is much faster than using ///
a revision range on the affected files. ///
///
The -e changelist# flag lists files modified by the specified ///
changelist. When used with the -Ro flag, only pending changes are ///
considered, to ensure that files opened for add are included. This ///
option also displays the change description. ///
///
The -O options modify the output as follows: ///
///
-Of output all revisions for the given files (this ///
option suppresses other* and resolve* fields) ///
///
-Ol output a fileSize and digest field for each revision ///
(this may be expensive to compute) ///
///
-Op output the local file path in both Perforce syntax ///
(//client/) as 'clientFile' and host form as 'path' ///
///
-Or output pending integration record information for ///
files opened on the current client, or if used with ///
'-e <change> -Rs', on the shelved change ///
///
-Os exclude client-related data from output ///
///
The -R option limits output to specific files: ///
///
-Rc files mapped in the client view ///
-Rh files synced to the client workspace ///
-Rn files opened not at the head revision ///
-Ro files opened ///
-Rr files opened that have been resolved ///
-Rs files shelved (requires -e) ///
-Ru files opened that need resolving ///
///
The -S option changes the order of output: ///
///
-St sort by filetype ///
-Sd sort by date ///
-Sr sort by head revision ///
-Sh sort by have revision ///
-Ss sort by filesize ///
///
For compatibility, the following flags are also supported: ///
-C (-Rc) -H (-Rh) -W (-Ro) -P (-Op) -l (-Ol) -s (-Os). ///
///
///
public IList GetFileMetaData(Options options, params FileSpec[] filespecs) { string[] paths = FileSpec.ToEscapedStrings(filespecs); P4.P4Command fstatCmd = new P4Command(this, "fstat", true, paths); P4.P4CommandResult r = fstatCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } List value = new List(); foreach (P4.TaggedObject obj in r.TaggedOutput) { FileMetaData fmd = new FileMetaData(); fmd.FromFstatCmdTaggedData(obj); value.Add(fmd); } return value; } public IList GetFileMetaData(IList filespecs, Options options) { return GetFileMetaData(options, filespecs.ToArray()); } /// /// Get the File objects associated with the passed-in FileSpec list. /// /// /// /// /// ///
p4 help files ///
///
files -- List files in the depot ///
///
p4 files [ -a ] [ -A ] [ -m max ] file[revRange] ... ///
///
List details about specified files: depot file name, revision, ///
file, type, change action and changelist number of the current ///
head revision. If client syntax is used to specify the file ///
argument, the client view mapping is used to determine the ///
corresponding depot files. ///
///
By default, the head revision is listed. If the file argument ///
specifies a revision, then all files at that revision are listed. ///
If the file argument specifies a revision range, the highest revision ///
in the range is used for each file. For details about specifying ///
revisions, see 'p4 help revisions'. ///
///
The -a flag displays all revisions within the specific range, rather ///
than just the highest revision in the range. ///
///
The -A flag displays files in archive depots. ///
///
The -m flag limits files to the first 'max' number of files. ///
///
///
public IList GetFiles(Options options, params FileSpec[] filespecs) { P4.P4Command fstatCmd = new P4Command(this, "files", true, FileSpec.ToStrings(filespecs)); P4.P4CommandResult r = fstatCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } List value = new List(); foreach (P4.TaggedObject obj in r.TaggedOutput) { File val = new File(); val.ParseFilesCmdTaggedData(obj); value.Add(val); } return value; } public IList GetFiles(IList filespecs, Options options) { return GetFiles(options, filespecs.ToArray()); } /// /// List selected directory paths in the repository. /// /// /// /// /// ///
p4 help dirs ///
///
dirs -- List depot subdirectories ///
///
p4 dirs [-C -D -H] [-S stream] dir[revRange] ... ///
///
List directories that match the specified file pattern (dir). ///
This command does not support the recursive wildcard (...). ///
Use the * wildcard instead. ///
///
Perforce does not track directories individually. A path is treated ///
as a directory if there are any undeleted files with that path as a ///
prefix. ///
///
By default, all directories containing files are listed. If the dir ///
argument includes a revision range, only directories containing files ///
in the range are listed. For details about specifying file revisions, ///
see 'p4 help revisions'. ///
///
The -C flag lists only directories that fall within the current ///
client view. ///
///
The -D flag includes directories containing only deleted files. ///
///
The -H flag lists directories containing files synced to the current ///
client workspace. ///
///
The -S flag limits output to depot directories mapped in a stream's ///
client view. ///
///
///
public IList GetDepotDirs(Options options, params string[] dirs) { P4.P4Command dirsCmd = new P4Command(this, "dirs", false, dirs); P4.P4CommandResult r = dirsCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } List value = new List(); foreach (P4.InfoLine l in r.InfoOutput) { value.Add(l.Info); } return value; } public IList GetDepotDirs(IList dirs, Options options) { return GetDepotDirs(options, dirs.ToArray()); } /// /// Return the contents of the files identified by the passed-in file specs. /// /// /// /// /// GetFileContents /// ///
p4 help print ///
///
print -- Write a depot file to standard output ///
///
p4 print [-a -o localFile -q] file[revRange] ... ///
///
Retrieve the contents of a depot file to the client's standard output. ///
The file is not synced. If file is specified using client syntax, ///
Perforce uses the client view to determine the corresponding depot ///
file. ///
///
By default, the head revision is printed. If the file argument ///
includes a revision, the specified revision is printed. If the ///
file argument has a revision range, then only files selected by ///
that revision range are printed, and the highest revision in the ///
range is printed. For details about revision specifiers, see 'p4 ///
help revisions'. ///
///
The -a flag prints all revisions within the specified range, rather ///
than just the highest revision in the range. ///
///
The -o localFile flag redirects the output to the specified file on ///
the client filesystem. ///
///
The -q flag suppresses the initial line that displays the file name ///
and revision. ///
///
///
public IList GetFileContents(Options options, params FileSpec[] filespecs) { P4.P4Command printCmd = new P4Command(this, "print", true, FileSpec.ToEscapedStrings(filespecs)); P4.P4CommandResult r = printCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } IList value = new List(); if (r.TaggedOutput != null) { if ((options == null) || (options.ContainsKey("-q") == false)) { foreach (P4.TaggedObject obj in r.TaggedOutput) { string path = string.Empty; string rev = string.Empty; if (obj.ContainsKey("depotFile")) { value.Add(obj["depotFile"]); } } } } value.Add(r.TextOutput); return value; } public IList GetFileContents(IList filespecs, Options options) { return GetFileContents(options, filespecs.ToArray()); } /// /// Get the revision history data for the passed-in file specs. /// /// /// See: /// /// ///
p4 help filelog ///
///
filelog -- List revision history of files ///
///
p4 filelog [-c changelist# -h -i -l -L -t -m maxRevs -s] file[revRange] ... ///
///
List the revision history of the specified files, from the most ///
recent revision to the first. If the file specification includes ///
a revision, the command lists revisions at or prior to the specified ///
revision. If the file specification includes a revision range, ///
the command lists only the specified revisions. See 'p4 help revisions' ///
for details. ///
///
The -c changelist# flag displays files submitted at the specified ///
changelist number. ///
///
The -i flag includes inherited file history. If a file was created by ///
branching (using 'p4 integrate'), filelog lists the revisions of the ///
file's ancestors up to the branch points that led to the specified ///
revision. File history inherited by renaming (using 'p4 move') is ///
always displayed regardless of whether -i is specified. ///
///
The -h flag displays file content history instead of file name ///
history. The list includes revisions of other files that were ///
branched or copied (using 'p4 integrate' and 'p4 resolve -at') to ///
the specified revision. Revisions that were replaced by copying ///
or branching are omitted, even if they are part of the history of ///
the specified revision. ///
///
The -t flag displays the time as well as the date. ///
///
The -l flag lists the full text of the changelist descriptions. ///
///
The -L flag lists the full text of the changelist descriptions, ///
truncated to 250 characters if longer. ///
///
The -m maxRevs displays at most 'maxRevs' revisions per file of ///
the file[rev] argument specified. ///
///
The -s flag displays a shortened form of filelog that omits ///
non-contributory integrations. ///
///
///
/// public IList GetFileHistory(Options options, params FileSpec[] filespecs) { P4.P4Command filesCmd = new P4Command(this, "filelog", true, FileSpec.ToEscapedStrings(filespecs)); P4.P4CommandResult r = filesCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } IList value = new List(); foreach (P4.TaggedObject obj in r.TaggedOutput) { int idx = 0; while (true) { string key = String.Format("rev{0}", idx); int revision = -1; if (obj.ContainsKey(key)) int.TryParse(obj[key], out revision); else break; int changelistid = -1; key = String.Format("change{0}", idx); if (obj.ContainsKey(key)) int.TryParse(obj[key], out changelistid); StringEnum action = "None"; key = String.Format("action{0}", idx); if (obj.ContainsKey(key)) action = obj[key]; DateTime date = new DateTime(); long unixTime = 0; key = String.Format("time{0}", idx); if (obj.ContainsKey(key)) unixTime = Int64.Parse(obj[key]); date = new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(unixTime); string username = null; key = String.Format("user{0}", idx); if (obj.ContainsKey(key)) username = obj[key]; string description = null; key = String.Format("desc{0}", idx); if (obj.ContainsKey(key)) description = obj[key]; string digest = null; key = String.Format("digest{0}", idx); if (obj.ContainsKey(key)) digest = obj[key]; long filesize = -1; key = String.Format("fileSize{0}", idx); if (obj.ContainsKey(key)) long.TryParse(obj[key], out filesize); string clientname = null; key = String.Format("client{0}", idx); if (obj.ContainsKey(key)) clientname = obj[key]; PathSpec depotpath = new DepotPath(obj["depotFile"]); FileType filetype = null; key = String.Format("type{0}", idx); if (obj.ContainsKey(key)) filetype = new FileType(obj[key]); List integrationsummaries = new List(); int idx2 = 0; key = String.Format("how{0},{1}", idx, idx2); while (obj.ContainsKey(key)) { string how = obj[key]; key = String.Format("file{0},{1}", idx, idx2); string frompath = obj[key]; key = String.Format("srev{0},{1}", idx, idx2); string srev = obj[key]; VersionSpec startrev = new Revision(-1); if (srev.StartsWith("#h") | srev.StartsWith("#n")) { if (srev.Contains("#none")) { startrev = Revision.None; } if (srev.Contains("#have")) { startrev = Revision.Have; } if (srev.Contains("#head")) { startrev = Revision.Head; } } else { srev = srev.Trim('#'); int rev = Convert.ToInt16(srev); startrev = new Revision(rev); } key = String.Format("erev{0},{1}", idx, idx2); string erev = obj[key]; VersionSpec endrev = new Revision(-1); if (erev.StartsWith("#h") | erev.StartsWith("#n")) { if (erev.Contains("#none")) { endrev = Revision.None; } if (srev.Contains("#have")) { endrev = Revision.Have; } if (srev.Contains("#head")) { endrev = Revision.Head; } } else { erev = erev.Trim('#'); int rev = Convert.ToInt16(erev); endrev = new Revision(rev); } RevisionIntegrationSummary integrationsummary = new RevisionIntegrationSummary( new FileSpec(new DepotPath(frompath), new VersionRange(startrev, endrev)), how); integrationsummaries.Add(integrationsummary); idx2++; key = String.Format("how{0},{1}", idx, idx2); } FileHistory fh = new FileHistory(revision, changelistid, action, date, username, filetype, description, digest, filesize, depotpath, clientname, integrationsummaries); value.Add(fh); idx++; } } return value; } public IList GetFileHistory(IList filespecs, Options options) { return GetFileHistory(options, filespecs.ToArray()); } /// /// Get content and existence diff details for two depot files. /// /// /// /// /// ///
p4 help diff ///
///
diff -- Display diff of client file with depot file ///
///
p4 diff [-d<flags> -f -m max -s<flag> -t] [file[rev] ...] ///
///
On the client machine, diff a client file against the corresponding ///
revision in the depot. The file is compared only if the file is ///
opened for edit or a revision is provided. See 'p4 help revisions' ///
for details about specifying revisions. ///
///
If the file specification is omitted, all open files are diffed. ///
This option can be used to view pending changelists. ///
///
The -d<flags> modify the output as follows: -dn (RCS), -dc[n] (context), ///
-ds (summary), -du[n] (unified), -db (ignore whitespace changes), ///
-dw (ignore whitespace), -dl (ignore line endings). The optional ///
argument to -dc specifies number of context lines. ///
///
The -f flag diffs every file, regardless of whether they are opened ///
or the client has synced the specified revision. This option can be ///
used to verify the contents of the client workspace. ///
///
The -m max flag limits output to the first 'max' number of files, ///
unless the -s flag is used, in which case it is ignored. ///
///
The -s options lists the files that satisfy the following criteria: ///
///
-sa Opened files that differ from the revision ///
in the depot or are missing. ///
///
-sb Files that have been opened for integrate, resolved, ///
and subsequently modified. ///
///
-sd Unopened files that are missing on the client. ///
///
-se Unopened files that differ from the revision ///
in the depot. ///
///
-sl Every unopened file, along with the status of ///
'same, 'diff', or 'missing' as compared to the ///
corresponding revision in the depot. ///
///
-sr Opened files that do not differ from the revision in ///
the depot. ///
///
The -t flag forces 'p4 diff' to diff binary files. ///
///
If the environment variable $P4DIFF is set, the specified diff ///
program is launched in place of the default Perforce client diff. ///
The -d<flags> option can be used to pass arguments to the diff ///
program. Because the -s flag is only implemented internally, any ///
-d<flags> option used with the -s<flag> is ignored. To configure a ///
diff program for Unicode files, set the environment variable ///
$P4DIFFUNICODE. Specify the file's character set as the first ///
argument to the program. ///
///
///
public IList GetDepotFileDiffs(string filespecleft, string filespecright, Options options) { P4.P4Command GetDepotFileDiffs = new P4Command(this, "diff2", true, filespecleft, filespecright); P4.P4CommandResult r = GetDepotFileDiffs.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } IList value = new List(); foreach (P4.TaggedObject obj in r.TaggedOutput) { DepotFileDiff val = new DepotFileDiff(); val.FromGetDepotFileDiffsCmdTaggedOutput(obj, _connection); value.Add(val); } return value; } /// /// Return FileAnnotation objects for the listed FileSpecs. /// /// /// /// /// ///
p4 help annotate ///
///
annotate -- Print file lines and their revisions ///
///
p4 annotate [-aciIq -d<flags>] file[revRange] ... ///
///
Prints all lines of the specified files, indicating the revision that ///
introduced each line into the file. ///
///
If the file argument includes a revision, then only revisions up to ///
the specified revision are displayed. If the file argument has a ///
revision range, only revisions within that range are displayed. For ///
details about specifying revisions, see 'p4 help revisions'. ///
///
The -a flag includes both deleted files and lines no longer present ///
at the head revision. In the latter case, both the starting and ending ///
revision for each line is displayed. ///
///
The -c flag directs the annotate command to output changelist numbers ///
rather than revision numbers for each line. ///
///
The -d<flags> change the way whitespace and/or line endings are ///
treated: -db (ignore whitespace changes), -dw (ignore whitespace), ///
-dl (ignore line endings). ///
///
The -i flag follows branches. If a file was created by branching, ///
'p4 annotate' includes the revisions of the source file up to the ///
branch point, just as 'p4 filelog -i' does. If a file has history ///
prior to being created by branching (such as a file that was branched ///
on top of a deleted file), -i ignores those prior revisions and ///
follows the source. -i implies -c. ///
///
The -I flag follows all integrations into the file. If a line was ///
introduced into the file by a merge, the source of the merge is ///
displayed as the changelist that introduced the line. If the source ///
itself was the result of an integration, that source is used instead, ///
and so on. -I implies -c. ///
///
The -q flag suppresses the one-line header that is displayed by ///
default for each file. ///
///
///
public IList GetFileAnnotations(IList filespecs, Options options) { P4.P4Command annotateCmd = new P4Command(this, "annotate", true, FileSpec.ToStrings(filespecs)); P4.P4CommandResult r = annotateCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } bool changelist = false; string opts; if (options != null) { opts = options.Keys.ToString(); if (opts.Contains("c")) { changelist = true; } } string dp = null; string line = null; int lower = -1; int upper = -1; IList value = new List(); //FileAnnotation fa = new FileAnnotation(new FileSpec(new DepotPath(dp), new VersionRange(lower, upper)), line); foreach (P4.TaggedObject obj in r.TaggedOutput) { if (obj.ContainsKey("depotFile")) { dp = obj["depotFile"]; line = null; lower = -1; upper = -1; continue; } if (obj.ContainsKey("lower")) { int l = -1; int.TryParse(obj["lower"], out l); lower = l; } if (obj.ContainsKey("upper")) { int u = -1; int.TryParse(obj["upper"], out u); upper = u; } if (obj.ContainsKey("data")) { line = obj["data"]; } if (dp != null && line != null && lower != -1 && upper != -1) { FileSpec fs = new FileSpec(); if (changelist == true) { fs = new FileSpec(new DepotPath(dp), new VersionRange(new ChangelistIdVersion(lower), new ChangelistIdVersion(upper))); } else { fs = new FileSpec(new DepotPath(dp), new VersionRange(new Revision(lower), new Revision(upper))); } FileAnnotation fa = new FileAnnotation(fs, line); value.Add(fa); } } return value; } /// /// Tag depot files with the passed-in label. /// /// /// /// /// /// ///
p4 help tag ///
///
tag -- Tag files with a label ///
///
p4 tag [-d -n] -l label file[revRange] ... ///
///
Tag associates the named label with the file revisions specified by ///
the file argument. After file revisions are tagged with a label, ///
revision specifications of the form '@label' can be used to refer ///
to them. ///
///
If the file argument does not include a revision specification, the ///
head revisions is tagged. See 'p4 help revisions' for revision ///
specification options. ///
///
If the file argument includes a revision range specification, only ///
the files with revisions in that range are tagged. Files with more ///
than one revision in the range are tagged at the highest revision. ///
///
The -d deletes the association between the specified files and the ///
label, regardless of revision. ///
///
The -n flag previews the results of the operation. ///
///
Tag can be used with an existing label (see 'p4 help labels') or ///
with a new one. An existing label can be used only by its owner, ///
and only if it is unlocked. (See 'p4 help label'). ///
///
To list the file revisions tagged with a label, use 'p4 files ///
@label'. ///
///
///
public IList TagFiles(IList filespecs, string labelid, Options options) { P4.P4Command tagCmd = new P4Command(this, "tag", true, FileSpec.ToStrings(filespecs)); options["-l"] = labelid; P4.P4CommandResult r = tagCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } IList value = new List(); foreach (P4.TaggedObject obj in r.TaggedOutput) { string revision = obj["rev"]; int rev = Convert.ToInt16(revision); VersionSpec version = new Revision(rev); DepotPath path = new DepotPath(obj["depotFile"]); FileSpec fs = new FileSpec(path, version); value.Add(fs); } return value; } /// /// List fixes affecting files and / or jobs and / or changelists. /// /// /// /// /// ///
p4 help fixes ///
///
fixes -- List jobs with fixes and the changelists that fix them ///
///
p4 fixes [-i -m max -c changelist# -j jobName] [file[revRange] ...] ///
///
'p4 fixes' list fixed jobs and the number of the changelist that ///
contains the fix.Fixes are associated with changelists using the ///
'p4 fix' command or by editing and submitting changelists. ///
///
The 'p4 fixes' command lists both submitted and pending changelists. ///
///
By default, 'p4 fixes' lists all fixes. This list can be limited ///
as follows: to list fixes for a specified job, use the -j jobName ///
flag. To list fixes for a specified changelist, use -c changelist#. ///
To list fixes that affect specified files, include the file argument. ///
The file pattern can include wildcards and revision specifiers. For ///
details about revision specifiers, see 'p4 help revisions' ///
///
The -i flag also includes any fixes made by changelists integrated ///
into the specified files. ///
///
The -m max flag limits output to the specified number of job ///
fixes. ///
///
///
public IList GetFixes(IList filespecs, Options options) { P4.P4Command fixesCmd = new P4Command(this, "fixes", true, FileSpec.ToStrings(filespecs)); P4.P4CommandResult r = fixesCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } IList value = new List(); foreach (P4.TaggedObject obj in r.TaggedOutput) { value.Add(Fix.FromFixesCmdTaggedOutput(obj)); } return value; } /// /// Get a list of matching lines in the passed-in file specs. /// /// /// /// /// /// ///
p4 help grep ///
///
grep -- Print lines matching a pattern ///
///
p4 grep [options] -e pattern file[revRange]... ///
///
options: -a -i -n -A <num> -B <num> -C <num> -t -s (-v|-l|-L) (-F|-G) ///
///
Searches files for lines that match the specified regular expression, ///
which can contain wildcards. The parser used by the Perforce server ///
is based on V8 regexp and might not be compatible with later parsers, ///
but the majority of functionality is available. ///
///
By default the head revision is searched. If the file argument includes ///
a revision specification, all corresponding revisions are searched. ///
If the file argument includes a revision range, only files in that ///
range are listed, and the highest revision in the range is searched. ///
For details about revision specifiers, see 'p4 help revisions'. ///
///
The -a flag searches all revisions within the specified range. By ///
default only the highest revision in the range is searched. ///
///
The -i flag causes the pattern matching to be case-insensitive. By ///
default, matching is case-sensitive. ///
///
The -n flag displays the matching line number after the file revision ///
number. By default, matches are displayed as revision#: <text>. ///
///
The -v flag displays files with non-matching lines. ///
///
The -F flag is used to interpret the pattern as a fixed string. ///
///
The -G flag is used to interpret the pattern as a regular expression, ///
which is the default behavior. ///
///
The -L flag displays the name of each selected file from which no ///
output would normally have been displayed. Scanning stops on the ///
first match. ///
///
The -l flag display the name of each selected file containing ///
matching text. Scanning stops on the first match. ///
///
The -s flag suppresses error messages that result from abandoning ///
files that have a maximum number of characters in a single line that ///
are greater than 4096. By default, an error is reported when grep ///
abandons such files. ///
///
The -t flag searches binary files. By default, only text files are ///
searched. ///
///
The -A <num> flag displays the specified number of lines of trailing ///
context after matching lines. ///
///
The -B <num> flag displays the specified number of lines of leading ///
context before matching lines. ///
///
The -C <num> flag displays the specified number of lines of output ///
context. ///
///
Regular expressions: ///
///
A regular expression is zero or more branches, separated by `|'. It ///
matches anything that matches one of the branches. ///
///
A branch is zero or more pieces, concatenated. It matches a match ///
for the first, followed by a match for the second, etc. ///
///
A piece is an atom possibly followed by `*', `+', or `?'. An atom ///
followed by `*' matches a sequence of 0 or more matches of the atom. ///
An atom followed by `+' matches a sequence of 1 or more matches of ///
the atom. An atom followed by `?' matches a match of the atom, or ///
the null string. ///
///
An atom is a regular expression in parentheses (matching a match for ///
the regular expression), a range (see below), `.' (matching any ///
single character), `^' (matching the null string at the beginning ///
of the input string), `$' (matching the null string at the end of ///
the input string), a `\' followed by a single character (matching ///
that character), or a single character with no other significance ///
(matching that character). ///
///
A range is a sequence of characters enclosed in `[]'. It normally ///
matches any single character from the sequence. If the sequence ///
begins with `^', it matches any single character not from the rest ///
of the sequence. If two characters in the sequence are separated by ///
`-', this is shorthand for the full list of ASCII characters between ///
them (e.g. `[0-9]' matches any decimal digit). To include a literal ///
`]' in the sequence, make it the first character (following a possible ///
`^'). To include a literal `-', make it the first or last character. ///
///
///
public IList GetFileLineMatches(IList filespecs, string pattern, Options options) { P4.P4Command grepCmd = new P4Command(this, "grep", true, FileSpec.ToStrings(filespecs)); options["-e"] = pattern; P4.P4CommandResult r = grepCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } IList value = new List(); foreach (P4.TaggedObject obj in r.TaggedOutput) { FileLineMatch val = new FileLineMatch(); val.ParseGrepCmdTaggedData(obj); value.Add(val); } return value; } /// /// Get a list of submitted integrations for the passed-in file specs. /// /// /// /// /// ///
p4 help integrated ///
///
integrated -- List integrations that have been submitted ///
///
p4 integrated [-r] [-b branch] [file ...] ///
///
The p4 integrated command lists integrations that have been submitted. ///
To list unresolved integrations, use 'p4 resolve -n'. To list ///
resolved but unsubmitted integrations, use 'p4 resolved'. ///
///
If the -b branch flag is specified, only files integrated from the ///
source to target files in the branch view are listed. Qualified ///
files are listed, even if they were integrated without using the ///
branch view. ///
///
The -r flag reverses the mappings in the branch view, swapping the ///
target files and source files. The -b branch flag is required. ///
///
///
public IList GetSubmittedIntegrations(IList filespecs, Options options) { P4.P4Command integratedCmd = new P4Command(this, "integrated", true, FileSpec.ToStrings(filespecs)); P4.P4CommandResult r = integratedCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } IList value = new List(); foreach (P4.TaggedObject obj in r.TaggedOutput) { FileIntegrationRecord val = new FileIntegrationRecord(); val.ParseIntegratedCmdTaggedData(obj); value.Add(val); } return value; } /// /// Get a list of Perforce protection entries for the passed-in file specs /// /// /// /// /// ///
p4 help protects ///
///
protects -- Display protections defined for a specified user and path ///
///
p4 protects [-a | -g group | -u user] [-h host] [-m] [file ...] ///
///
'p4 protects' displays the lines from the protections table that ///
apply to the current user. The protections table is managed using ///
the 'p4 protect' command. ///
///
If the -a flag is specified, protection lines for all users are ///
displayed. If the -g group flag or -u user flag is specified, ///
protection lines for that group or user are displayed. ///
///
If the -h host flag is specified, the protection lines that apply ///
to the specified host (IP address) are displayed. ///
///
If the -m flag is given, a single word summary of the maximum ///
access level is reported. Note that this summary does not take ///
exclusions into account. ///
///
If the file argument is specified, protection lines that apply to ///
the specified files are displayed. ///
///
The -a/-g/-u flags require 'super' access granted by 'p4 protect'. ///
///
///
public IList GetProtectionEntries(IList filespecs, Options options) { P4.P4Command protectsCmd = new P4Command(this, "protects", true, FileSpec.ToStrings(filespecs)); P4.P4CommandResult r = protectsCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } IList value = new List(); foreach (P4.TaggedObject obj in r.TaggedOutput) { StringEnum mode = obj["perm"]; StringEnum type = "User"; if (obj.ContainsKey("isgroup")) { type = "Group"; } string name = obj["user"]; string host = obj["host"]; string path = obj["depotFile"]; ProtectionEntry pte = new ProtectionEntry(mode, type, name, host, path); value.Add(pte); } return value; } /// /// List Perforce users assigned to review files. /// /// /// /// /// ///
p4 help reviews ///
///
reviews -- List the users who are subscribed to review files ///
///
p4 reviews [-c changelist#] [file ...] ///
///
'p4 reviews' lists all users who have subscribed to review the ///
specified files, the files in the specified changelist, or all files ///
(the default). To subscribe to review files, issue the 'p4 user' ///
command and edit the 'Reviews field'. ///
///
///
public IList GetReviewers (IList filespecs, Options options) { P4.P4Command reviewsCmd = new P4Command(this, "reviews", true, FileSpec.ToStrings(filespecs)); P4.P4CommandResult r = reviewsCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } List value = new List(); foreach (P4.TaggedObject obj in r.TaggedOutput) { string id = obj["user"]; string fullname = obj["name"]; string password = string.Empty; string emailaddress = obj["email"]; DateTime updated = DateTime.MinValue; DateTime accessed = DateTime.MinValue; string jobview = string.Empty; List reviews = new List(); UserType type = UserType.Standard; FormSpec spec = new FormSpec(null,null, null, null, null, null, null); User user = new User(id, fullname, password, emailaddress, updated, accessed, jobview, reviews, type, spec); value.Add(user); } return value; } /// /// Get a FormSpec of the specified form type. /// /// /// /// /// ///
p4 help spec ///
///
spec -- Edit spec definitions (unsupported) ///
///
p4 spec [-d -i -o] type ///
///
Edit any type of specification: branch, change, client, depot, ///
group, job, label, spec, stream, trigger, typemap, or user. Only ///
the comments and the formatting hints can be changed. Any fields ///
that you add during editing are discarded when the spec is saved. ///
///
'p4 jobspec' is equivalent to 'p4 spec job', and any custom spec ///
(include the job spec) can be deleted with 'p4 spec -d type'. ///
///
///
public FormSpec GetFormSpec(Options options, string spectype) { StringList cmdArgs = new StringList(); cmdArgs.Add(spectype); P4.P4Command specCmd = new P4Command(this, "spec", true, cmdArgs); P4.P4CommandResult r = specCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } foreach (P4.TaggedObject obj in r.TaggedOutput) { FormSpec val = FormSpec.FromSpecCmdTaggedOutput(obj); return val; } return null; } /// /// Get the repository's trigger table. /// /// /// /// ///
p4 help triggers ///
///
triggers -- Modify list of server triggers ///
///
p4 triggers ///
p4 triggers -o ///
p4 triggers -i ///
///
'p4 triggers' edits the table of triggers, which are used for ///
change submission validation, form validation, external authentication, ///
external job fix integration, and external archive integration. ///
///
Triggers are administrator-defined commands that the server runs ///
to perform the following: ///
///
Validate changelist submissions. ///
///
The server runs changelist triggers before the file transfer, ///
between file transfer and changelist commit, or after the commit ///
///
Validate shelve operations. ///
///
The server runs shelve triggers before files are shelved, after ///
files are shelved, or when shelved files have been discarded ///
(via shelve -d). ///
///
Manipulate and validate forms. ///
///
The server runs form-validating triggers between generating ///
and outputting the form, between inputting and parsing the ///
form, between parsing and saving the form, or when deleting ///
the form. ///
///
Authenticate or change a user password. ///
///
The server runs authentication triggers to either validate ///
a user password during login or when setting a new password. ///
///
Intercept job fix additions or deletions. ///
///
The server run fix triggers prior to adding or deleting a fix ///
between a job and changelist. ///
///
Access external archive files. ///
///
For files with the +X filetype modifier, the server runs an ///
archive trigger to read, write, or delete files in the archive. ///
///
The trigger form has a single entry 'Triggers', followed by any ///
number of trigger lines. Triggers are executed in the order listed ///
and if a trigger fails, subsequent triggers are not run. A trigger ///
succeeds if the executed command exits returning 0 and fails otherwise. ///
Normally the failure of a trigger prevents the operation from ///
completing, except for the commit triggers, which run after the ///
operation is complete. ///
///
Each trigger line contains a trigger name, a trigger type, a depot ///
file path pattern or form type, and a command to run. ///
///
Name: The name of the trigger. For change triggers, a run of the ///
same trigger name on contiguous lines is treated as a single ///
trigger so that multiple paths can be specified. Only the ///
command of the first such trigger line is used. ///
///
Type: When the trigger is to execute: ///
///
archive: ///
Execute an archive trigger for the server to access ///
any file with the +X filetype modifier. ///
///
auth-check: ///
service-check: ///
Execute an authentication check trigger to verify a ///
user's password against an external password manager ///
during login or when setting a new password. ///
///
auth-check-sso: ///
Facilitate a single sign-on user authentication. This ///
configuration requires two programs or scripts to run; ///
one on the client, the other on the server. ///
///
client: ///
Set the environment variable 'P4LOGINSSO' to point to ///
a script that can be executed to obtain the user's ///
credentials or other information that the server ///
trigger can verify. The client-side script must ///
write the message to the standard output ///
(max length 128K). ///
///
Example: P4LOGINSSO=/Users/joe/bin/runsso ///
///
The 'server address' can be optionally passed to the ///
client script by appending %serverAddress% to the ///
client command string, as in: ///
///
P4LOGINSSO="/Users/joe/bin/runsso %serverAddress%" ///
///
server: ///
Execute an authentication (sso) trigger that gets ///
this message from the standard input and returns an ///
exit status of 0 (for verified) or otherwise failed. ///
///
Example: ///
sso auth-check-sso auth "/secure/verify %user%" ///
///
The user must issue the 'p4 login' command, but no ///
password prompting is invoked. If the server ///
determines that the user is valid, they are issued a ///
Perforce ticket just as if they had logged in with a ///
password. ///
///
Pre-2007.2 clients cannot run a client-side single ///
sign-on. Specifying an 'auth-check' trigger as a backup ///
for a user to gain access will prompt the user for a ///
password if it's an older client or P4LOGINSSO has not ///
been configured. ///
///
Unlike passwords which are encrypted, the sso message is ///
sent to the server in clear text. ///
///
auth-set: ///
Execute an authentication set trigger to send a new ///
password to an external password manager. ///
///
change-submit: ///
Execute pre-submit trigger after changelist has been ///
created and files locked but prior to file transfer. ///
///
change-content: ///
Execute mid-submit trigger after file transfer but prior ///
to commit. Files can be accessed by the 'p4 diff2', ///
'p4 files', 'p4 fstat', and 'p4 print' commands using ///
the revision specification '@=change', where 'change' is ///
the pending changelist number passed as %changelist%. ///
///
change-commit: ///
Execute post-submit trigger after changelist commit. ///
///
fix-add: ///
Execute fix trigger prior to adding a fix. The special ///
variable %jobs% is available for expansion and must be ///
the last argument to the trigger as it expands to one ///
argument for each job listed on the 'p4 fix' command. ///
///
fix-delete: ///
Execute fix trigger prior to deleting a fix. The special ///
variable %jobs% is available for expansion and must be ///
the last argument to the trigger as it expands to one ///
argument for each job listed on the 'p4 fix -d' command. ///
///
form-out: ///
Execute form trigger on generation of form. Trigger may ///
modify form. ///
///
form-in: ///
Execute form trigger on input of form before its contents ///
are parsed and validated. Trigger may modify form. ///
///
form-save: ///
Execute form trigger prior to save of form after its ///
contents are parsed. ///
///
form-commit: ///
Execute form trigger after it has been committed, allowing ///
access to automatically generated fields (jobname, dates ///
etc). It cannot modify the form. This trigger for job ///
forms is run by 'p4 job' and 'p4 fix' (after the status ///
is updated), 'p4 change' (if the job is added or deleted) ///
and 'p4 submit' (if the job is associated with the change). ///
The 'form-commit' trigger has access to the new job name ///
created with 'p4 job', while the 'form-in' and 'form-save' ///
triggers are run before the job name is created. The ///
special variable %action% is available on the job ///
'form-commit' trigger command line, and is expanded when ///
the job is modified by a fix. ///
///
form-delete: ///
Execute form trigger prior to delete of form after its ///
contents are parsed. ///
///
shelve-submit: ///
Execute pre-shelve trigger after changelist has been ///
created but prior to file transfer. ///
///
shelve-commit: ///
Execute post-shelve trigger after files are shelved. ///
///
shelve-delete: ///
Execute shelve trigger prior to discarding shelved files. ///
///
Path: For change and submit triggers, a file pattern to match files ///
in the changelist. This file pattern can be an exclusion ///
mapping (-pattern), to exclude files. For form triggers, the ///
name of the form (branch, client, etc). For fix triggers ///
'fix' is required as the path value. For authentication ///
triggers, 'auth' is required as the path value. For archive ///
triggers, a file pattern to match the name of the file being ///
accessed in the archive. Note that, due to lazy copying when ///
branching files, the name of the file in the archive can not ///
be the same as the name of the file in the depot. ///
///
Command: The OS command to run for validation. If the command ///
contains spaces, enclose it in double quotes. The ///
following variables are expanded in the command string: ///
///
%client% -- the client issuing the command ///
%clienthost% -- the hostname of the client ///
%clientip% -- the IP address of the client ///
%serverhost% -- the hostname of the server ///
%serverip% -- the IP address of the server ///
%serverport% -- the IP address:port of the server ///
%serverroot% -- the value of the server's $P4ROOT ///
%user% -- the user issuing the command ///
///
%changelist% -- the changelist being submitted ///
%changeroot% -- the root path of files submitted ///
%oldchangelist% -- the pre-commit changelist number ///
///
(More information can be gathered about the ///
changelist being submitted by running ///
'p4 describe %changelist%'.) ///
///
%formfile% -- path to temp file containing form ///
%formname% -- the form's name (branch name, etc) ///
%formtype% -- the type of form (branch, etc) ///
%action% -- added/deleted/submitted on job form-commit ///
///
%jobs% -- list of job names for fix triggers ///
///
%op% -- read/write/delete for archive access ///
%file% -- name of archive file ///
%rev% -- revision of archive file ///
///
The command's standard input is empty for change, shelve, ///
fix, and auth triggers; it is the form contents for form ///
triggers; and it is the file content for the archive trigger. ///
///
If the command fails, the command's standard output (not ///
error output) is sent to the client as the text of a trigger ///
failure error message. ///
///
If the command succeeds, the command's standard output is ///
sent as an unadorned message to the client for all triggers ///
except archive triggers; for archive triggers, the command's ///
standard output is the file content. ///
///
The -o flag writes the trigger table to the standard output. ///
The user's editor is not invoked. ///
///
The -i flag reads the trigger table from the standard input. ///
The user's editor is not invoked. ///
///
'p4 triggers' requires 'super' access granted by 'p4 protect'. ///
///
///
public IList GetTriggerTable(Options options) { P4.P4Command triggersCmd = new P4Command(this, "triggers", true); P4.P4CommandResult r = triggersCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } List value = new List(); foreach (P4.TaggedObject obj in r.TaggedOutput) { System.Text.StringBuilder sb = new StringBuilder(); foreach (KeyValuePair key in obj) { sb.Remove(0, sb.Length); sb.AppendLine((string.Format("{0} {1}", key.Key.ToString(), key.Value))); string line = sb.ToString(); if (line.StartsWith("Triggers")) { line = line.Trim(); string[] entries = line.Split(' '); string name = entries[1]; string ent = entries[2]; ent = ent.Replace("-",""); StringEnum type = ent; string path = entries[3]; string command = entries[4] + " " + entries[5]; string ord = entries[0]; ord = ord.Remove(0, 8); int order = 0; order = Convert.ToInt16(ord); Trigger trig = new Trigger(name, order, type, path, command); value.Add(trig); } } } return value; } /// /// Get the repository's type map. /// /// /// /// runs the command p4 typemap -o /// /// ///
p4 help typemap ///
///
typemap -- Edit the filename-to-filetype mapping table ///
///
p4 typemap ///
p4 typemap -o ///
p4 typemap -i ///
///
'p4 typemap' edits a name-to-type mapping table for 'p4 add', which ///
uses the table to assign a file's filetype based on its name. ///
///
The typemap form has a single field, 'TypeMap', followed by any ///
number of typemap lines. Each typemap line contains a filetype ///
and a depot file path pattern: ///
///
Filetype: See 'p4 help filetypes' for a list of valid filetypes. ///
///
Path: Names to be mapped to the filetype. The mapping is ///
a file pattern in depot syntax. When a user adds a file ///
matching this pattern, its default filetype is the ///
file type specified in the table. To exclude files from ///
the typemap, use exclusionary (-pattern) mappings. ///
To match all files anywhere in the depot hierarchy, ///
the pattern must begin with '//...'. To match files ///
with a specified suffix, use '//.../*.suffix' or ///
use '//....suffix' (four dots). ///
///
Later entries override earlier entries. If no matching entry is found ///
in the table, 'p4 add' determines the filetype by examining the file's ///
contents and execution permission bits. ///
///
The -o flag writes the typemap table to standard output. The user's ///
editor is not invoked. ///
///
The -i flag reads the typemap table from standard input. The user's ///
editor is not invoked. ///
///
'p4 typemap' requires 'admin' access, which is granted by 'p4 protect'. ///
///
///
public IList GetTypeMap() { P4.P4Command typemapCmd = new P4Command(this, "typemap", true, "-o"); P4.P4CommandResult r = typemapCmd.Run(); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } List value = new List(); foreach (P4.TaggedObject obj in r.TaggedOutput) { int ord = 0; string key = String.Format("TypeMap{0}", ord); while (obj.ContainsKey(key)) { value.Add(new TypeMapEntry(obj[key])); ord++; key = String.Format("TypeMap{0}", ord); } return value; } return value; } //public string CreateSpec(List map) //{ // StringBuilder val = new StringBuilder(map.Count * 256); // val.AppendLine("TypeMap:"); // for (int idx = 0; idx < map.Count; idx++) // { // val.AppendLine(String.Format("/t{0}", map[idx].ToString())); // } // return base.ToString(); //} /// /// Get the repository's protection table. /// /// /// /// ///
p4 help protect ///
///
protect -- Modify protections in the server namespace ///
///
p4 protect ///
p4 protect -o ///
p4 protect -i ///
///
'p4 protect' edits the protections table in a text form. ///
///
Each line in the table contains a protection mode, a group/user ///
indicator, the group/user name, client host ID and a depot file ///
path pattern. Users receive the highest privilege that is granted ///
on any line. ///
///
Note: remote depot are accessed using the pseudo-user 'remote'. ///
To control access from other servers that define your server as ///
a remote server, grant appropriate permissions to the 'remote' user. ///
///
Mode: The permission level or right being granted or denied. ///
Each permission level includes all the permissions above ///
it, except for 'review'. Each permission only includes ///
the specific right and no lesser rights. This approach ///
enables you to deny individual rights without having to ///
re-grant lesser rights. Modes prefixed by '=' are rights. ///
All other modes are permission levels. ///
///
Valid modes are: ///
///
list - users can see names but not contents of files; ///
users can see all non-file related metadata ///
(clients, users, changelists, jobs, etc.) ///
///
read - users can sync, diff, and print files ///
///
open - users can open files (add, edit. delete, ///
integrate) ///
///
write - users can submit open files ///
///
admin - permits those administrative commands and ///
command options that don't affect the server's ///
security. ///
///
super - access to all commands and command options. ///
///
review - permits access to the 'p4 review' command; ///
implies read access ///
///
=read - if this right is denied, users can't sync, ///
diff, or print files ///
///
=branch - if this right is denied, users are not ///
permitted to use files as a source ///
for 'p4 integrate' ///
///
=open = if this right is denied, users cannot open ///
files (add, edit, delete, integrate) ///
///
=write = if this right is denied, users cannot submit ///
open files ///
///
Group/User indicator: specifies the grantee is a group or user. ///
///
Name: A Perforce group or user name; can include wildcards. ///
///
Host: The IP address of a client host; can include wildcards. ///
///
Path: The part of the depot to which access is being granted ///
or denied. To deny access to a depot path, preface the ///
path with a "-" character. These exclusionary mappings ///
apply to all access levels, even if only one access ///
level is specified in the first field. ///
///
The -o flag writes the protection table to the standard output. ///
The user's editor is not invoked. ///
///
The -i flag reads the protection table from the standard input. ///
The user's editor is not invoked. ///
///
After protections are defined, 'p4 protect' requires 'super' ///
access. ///
///
///
public IList GetProtectionTable(Options options) { P4.P4Command protectCmd = new P4Command(this, "protect", true); P4.P4CommandResult r = protectCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } List value = new List(); foreach (P4.TaggedObject obj in r.TaggedOutput) { System.Text.StringBuilder sb = new StringBuilder(); foreach (KeyValuePair key in obj) { sb.Remove(0, sb.Length); sb.AppendLine((string.Format("{0} {1}", key.Key.ToString(), key.Value))); string line = sb.ToString(); if (line.StartsWith("Protections")) { line = line.Trim(); string[] entries = line.Split(' '); StringEnum mode = entries[1]; StringEnum type = entries[2]; string grouporusername = entries[3]; string host = entries[4]; string path = entries[5]; ProtectionEntry pe = new ProtectionEntry(mode, type, grouporusername, host, path); value.Add(pe); } } } return value; } /// /// Get the Perforce counters for this repository. /// /// /// /// ///
p4 help counters ///
///
counters -- Display list of known counters ///
///
p4 counters ///
///
Lists the counters in use by the server. The server ///
uses the following counters directly: ///
///
change Current change number ///
job Current job number ///
journal Current journal number ///
lastCheckpointAction Data about the last complete checkpoint ///
logger Event log index used by 'p4 logger' ///
traits Internal trait lot number used by 'p4 attribute' ///
upgrade Server database upgrade level ///
///
Other counters can be created by the 'p4 counter' or 'p4 review' ///
commands. ///
///
The names 'minClient', 'minClientMessage', 'monitor', ///
'security', and 'unicode' are reserved names: do not use them ///
as ordinary counters. ///
///
For general-purpose server configuration, see 'p4 help configure'. ///
///
///
public IList GetCounters(Options options) { P4.P4Command countersCmd = new P4Command(this, "counters", true); P4.P4CommandResult r = countersCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } IList val = new List(); foreach (P4.TaggedObject obj in r.TaggedOutput) { string name = obj["counter"]; string value = obj["value"]; Counter counter = new Counter(name, value); val.Add(counter); } return val; } /// /// Get a named Perforce counter value from the repository. /// /// /// /// /// ///
p4 help counter ///
///
counter -- Display, set, or delete a counter ///
///
p4 counter name ///
p4 counter [-f] name value ///
p4 counter [-f] -d name ///
p4 counter [-f] -i name ///
///
The first form displays the value of the specified counter. ///
///
The second form sets the counter to the specified value. ///
///
The third form deletes the counter. This option usually has the ///
same effect as setting the counter to 0. ///
///
The -f flag sets or deletes counters used by Perforce, which are ///
listed by 'p4 help counters'. Important: Never set the 'change' ///
counter to a value that is lower than its current value. ///
///
The -i flag increments a counter by 1 and returns the new value. ///
This option is used instead of a value argument and can only be ///
used with numeric counters. ///
///
Counters can be assigned textual values as well as numeric ones, ///
despite the name 'counter'. ///
///
'p4 counter' requires 'review' access granted by 'p4 protect'. ///
The -f flag requires that the user be an operator or have 'super' ///
access. ///
///
///
public Counter GetCounter(String name, Options options) { P4.P4Command counterCmd = new P4.P4Command(_connection, "counter", true, name); P4.P4CommandResult r = counterCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } if ((r.TaggedOutput == null) || (r.TaggedOutput.Count <= 0)) { return null; } foreach (P4.TaggedObject obj in r.TaggedOutput) { string countername = obj["counter"]; string value = obj["value"]; Counter counter = new Counter(countername, value); return counter; } return null; } /// /// Delete a Perforce counter from the repository. /// /// /// /// /// ///
p4 help counter ///
///
counter -- Display, set, or delete a counter ///
///
p4 counter name ///
p4 counter [-f] name value ///
p4 counter [-f] -d name ///
p4 counter [-f] -i name ///
///
The first form displays the value of the specified counter. ///
///
The second form sets the counter to the specified value. ///
///
The third form deletes the counter. This option usually has the ///
same effect as setting the counter to 0. ///
///
The -f flag sets or deletes counters used by Perforce, which are ///
listed by 'p4 help counters'. Important: Never set the 'change' ///
counter to a value that is lower than its current value. ///
///
The -i flag increments a counter by 1 and returns the new value. ///
This option is used instead of a value argument and can only be ///
used with numeric counters. ///
///
Counters can be assigned textual values as well as numeric ones, ///
despite the name 'counter'. ///
///
'p4 counter' requires 'review' access granted by 'p4 protect'. ///
The -f flag requires that the user be an operator or have 'super' ///
access. ///
///
///
public Object DeleteCounter(String name, Options options) { StringList cmdArgs = new StringList(); cmdArgs.Add("-f"); cmdArgs.Add("-d"); cmdArgs.Add(name); P4.P4Command delcounterCmd = new P4Command(this, "counter", false, cmdArgs); P4.P4CommandResult r = delcounterCmd.Run(options); if (r.Success != true) { P4Exception.Throw(r.ErrorList); return null; } return r.InfoOutput; } #region IDisposable Members public void Dispose() { _connection.Dispose(); } #endregion } }