here's something i've been using. i haven't felt it's good enuf to be sourceforge'd, but it's worked for me.
it works w/ nant 0.8.2 (i.e. before the namespace revamp), so it might need some refactoring. it's invoked like so: sync: <p4 verbose="${Trace.P4}" failonerror="false" action="sync" files="${Dir.Leap.Commands}..." /> add files to a changelist for edit/add: <p4 verbose="${Trace.P4}" action="edit" changelist="${P4.ChangeList}" files="${p}gen*.cs" /> <p4 verbose="${Trace.P4}" action="add" changelist="${P4.ChangeList}" files="${Dir.Work.Sql.Gen}*.sql" /> <p4 verbose="${Trace.P4}" action="edit" changelist="${P4.ChangeList}" files="${Dir.Leap.Sql.Gen}*.sql" /> submit them: <p4 verbose="${Trace.P4}" action="submit" changelist="${P4.ChangeList}" /> or not: <p4 verbose="${Trace.P4}" action="revert" options="-a" changelist="${P4.ChangeList}" /> creating a label involves creating a label file and submitting it like so: <p4 verbose="${Trace.P4}" action="label" labelfile="${File.Label}" /> there's a kludge in the task that checks for a global property ${Is.Lan} to be true. the caller might set Is.Lan false in order to make the task bail w/o working. this is needed when you're using the build files off line. otherwise, for simpler p4 tasks, i just <exec program="p4" .../> hth -----8<--------------- using System; using System.IO; using System.Text.RegularExpressions; using SourceForge.NAnt; using SourceForge.NAnt.Attributes; namespace NAnt.Contrib.Tasks { [TaskName("p4")] public class P4Task : Task { string _action = null; /// <summary> /// the actions for p4. possible values are: /// sync : req: files /// edit : req: files, changelist /// add : req: files, changelist /// submit : req: changelist OR files /// revert : req: changelist OR files; optional: options /// label : req: labelfile /// </summary> [TaskAttribute( "action", Required=true)] public string Action { get { return _action; } set { _action = value; } } string _changeList = null; [TaskAttribute( "changelist", Required=false)] public string ChangeList { get { return _changeList; } set { _changeList = value; } } string _labelFile = null; [TaskAttribute( "labelfile", Required=false)] /// <summary> /// required for action = label /// </summary> public string LabelFile { get { return _labelFile; } set { _labelFile = value; } } string _files = null; [TaskAttribute( "files", Required=false)] public string Files { get { return _files; } set { _files = value; } } string _options = string.Empty; /// <summary> /// any text that goes bet. the command and the other args (eg: -n ) /// applied on actions= submit or revert /// </summary> [TaskAttribute( "options", Required=false)] public string Options { get { return _options; } set { _options = value; } } private void showAction( string format, params object[] prms ) { if ( ( Project != null) && this.Verbose ) Log.WriteLine( string.Format( format, prms ) ); } protected override void ExecuteTask() { Log.WriteLine( LogPrefix + "action={0} changelist=\"{1}\" files=\"{2}\" labelfile=\"{3}\" options=\"{4}\"", Action, ChangeList, Files, LabelFile, Options ); bool onLan = true; if ( ( Project != null ) && ( Project.Properties[ "Is.Lan" ] != null ) ) onLan = Convert.ToBoolean( Project.Properties[ "Is.Lan" ] ); if ( !onLan ) { showAction( "No LAN, no P4! action={0} files={1}", _action, _files ); return; } string runStr = null; string output = null; int exitCode = -1; string changeListParam = string.Empty; if ( string.Compare( _action, "add", true ) == 0 ) { assertPropFiles(); string[] files = Directory.GetFiles( Path.GetDirectoryName( _files ), Path.GetFileName( _files) ) ; if ( files.Length == 0 ) { exitCode = 0; output = "No file(s) found to add." ; } else { changeListParam = string.Concat( "-c ", getChangeList() ); exitCode = RunProcess( "p4", string.Format( "add {0} {1}", changeListParam, _files ), null, ref output ); } } else if ( string.Compare( _action, "edit", true ) == 0 ) { assertPropFiles(); changeListParam = string.Concat( "-c ", getChangeList() ); exitCode = RunProcess( "p4", string.Format( "edit {0}", _files ), null, ref output ); if ( changeListParam != string.Empty ) exitCode = RunProcess( "p4", string.Format( "reopen {0} {1}", changeListParam, _files ), null, ref output ); } else if ( string.Compare( _action, "sync", true ) == 0 ) { assertPropFiles(); exitCode = RunProcess( "p4", string.Format( "sync {0}", _files ), null, ref output ); } else if (( string.Compare( _action, "submit", true ) == 0 ) || ( string.Compare( _action, "revert", true ) == 0 ) ) { changeListParam = string.Concat( "-c ", getChangeList() ); if ( ( changeListParam != string.Empty ) && ( _files != null) && ( _files != string.Empty ) ) throw new BuildException( "Cannot have both files and changelist set when action = " + _action ); else if ( changeListParam != string.Empty ) runStr = string.Format( "{0} {1} {2}", _action, _options, changeListParam ); else if ( ( _files != null ) && ( _files != string.Empty ) ) runStr = string.Format( "{0} {1} {2}", _action, _options, _files ); if ( runStr == null ) throw new BuildException( string.Format( "{0} action requires either files or changelist.", _action ) ); exitCode = RunProcess( "p4", runStr, null, ref output ); } else if ( string.Compare( _action, "label", true ) == 0 ) { if ( ( _labelFile == null ) || ( _labelFile == string.Empty ) ) throw new BuildException( "labelfile is a required property" ); if ( !File.Exists( LabelFile ) ) throw new BuildException( string.Format( "{0} not found", LabelFile ) ); string labelText = Frogware.Utils.ReadTextFromFile( LabelFile ); string labelName = getLabelName( labelText ); exitCode = RunProcess( "p4", "label -i", labelText, ref output ); if ( exitCode != 0 ) throw new BuildException( string.Format( "P4 LABEL returned EXITCODE = {0}", exitCode ) ); exitCode = RunProcess( "p4", string.Format( "labelsync -l {0}", labelName), null ); // don't take the output if ( exitCode != 0 ) throw new BuildException( string.Format( "P4 LABEL (SYNC) returned EXITCODE = {0}", exitCode ) ); } else { throw new BuildException( string.Format( "unknown action = {0}", _action ) ); } showAction( output ); if ( exitCode != 0 ) throw new BuildException( string.Format( "P4 returned EXITCODE = {0}\n** Output follows: ** \n{1}", exitCode, output ) ); } private string getLabelName( string labelText ) { Regex rex = new Regex( @"Label:\s*(?'name'\S+)" ); Match m = rex.Match( labelText ); if ( !m.Success ) throw new BuildException( string.Format( "invalid label file: {0}", LabelFile )); return m.Groups["name"].Value; } private void assertPropFiles() { if ( ( _files == null ) || ( _files == string.Empty ) ) throw new BuildException( "files is a required property" ); } private string getChangeList() { if ( _changeList == null ) return string.Empty; string testOut = getProcessOutput( "p4", string.Format( "changes -s pending -u {0}", Environment.UserName.ToLower() ), null ); string[] lines = testOut.Split( '\n' ); foreach( string line in lines ) { if ( line.IndexOf( _changeList ) > -1 ) { string[] s2 = line.Split( ' ' ); // poor manz regex return s2[ 1 ]; } } // create new changelist string changeListDef = string.Concat( "Change: new\n", "Client: ", Environment.MachineName.ToLower(), "\n", "User: ", Environment.UserName.ToLower(), "\n", "Status: new\nDescription:\n ", _changeList + "\nFiles:\n\n" ); string output = getProcessOutput( "p4", "change -i", changeListDef ); string[] s = output.Split( ' ' ); // poor manz regex if ( ( s.Length == 3) && ( s[0] == "Change" ) && ( s[2].StartsWith( "created." ) ) ) return s[ 1 ]; else { throw new BuildException( string.Format( "Unexpected P4 output = {0}", output)); } } private string getProcessOutput( string exe, string prms, string input ) { string output = null; int exitCode = RunProcess( exe, prms, input, ref output ); return output; } public int RunProcess( string exe, string prms, string input, ref string output ) { showAction( "{0} {1}", exe, prms ); System.Diagnostics.Process p = new System.Diagnostics.Process(); System.Diagnostics.ProcessStartInfo si = new System.Diagnostics.ProcessStartInfo( exe, prms ); si.UseShellExecute = false; si.RedirectStandardOutput = true; si.RedirectStandardInput = ( input != null ); p.StartInfo = si; p.Start(); if ( input != null ) { StreamWriter sw = p.StandardInput; sw.Write( input ); sw.Close(); } output = p.StandardOutput.ReadToEnd(); p.WaitForExit(); showAction( output ); return p.ExitCode; } public int RunProcess( string exe, string prms, string input ) { showAction( "{0} {1}", exe, prms ); System.Diagnostics.Process p = new System.Diagnostics.Process(); System.Diagnostics.ProcessStartInfo si = new System.Diagnostics.ProcessStartInfo( exe, prms ); si.UseShellExecute = false; si.RedirectStandardOutput = false; si.RedirectStandardInput = ( input != null ); p.StartInfo = si; p.Start(); if ( input != null ) { StreamWriter sw = p.StandardInput; sw.Write( input ); sw.Close(); } p.WaitForExit(); return p.ExitCode; } } } > -----Original Message----- > From: [EMAIL PROTECTED] > [mailto:[EMAIL PROTECTED] On Behalf Of > Ben Lowery > Sent: Tuesday, November 04, 2003 12:43 > To: [EMAIL PROTECTED] > Subject: [Nant-users] Perforce Tasks? > > > Has anyone worked up some Perforce tasks for NAnt? If so, > would you be willing to share them? > > Thanks, > > --b > > > > > ------------------------------------------------------- > This SF.net email is sponsored by: SF.net Giveback Program. > Does SourceForge.net help you be more productive? Does it > help you create better code? SHARE THE LOVE, and help us > help YOU! Click Here: http://sourceforge.net/donate/ > _______________________________________________ > Nant-users mailing list > [EMAIL PROTECTED] > https://lists.sourceforge.net/lists/listinfo/n> ant-users > ------------------------------------------------------- This SF.net email is sponsored by: SF.net Giveback Program. Does SourceForge.net help you be more productive? Does it help you create better code? SHARE THE LOVE, and help us help YOU! Click Here: http://sourceforge.net/donate/ _______________________________________________ Nant-users mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/nant-users