Ian
Good stuff.
Any chance of getting those into nantcontrib or whereever they fit best? Would be nice to have some perforce tasks in a position that they can be actively developed.
Brett
-----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Jean Rajotte Sent: Thursday, 20 November 2003 2:50 AM To: [EMAIL PROTECTED]; [EMAIL PROTECTED] Subject: RE: [Nant-users] Perforce Tasks?
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
-------------------------------------------------------
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
--
Ian MacLean, Developer, ActiveState, a division of Sophos
http://www.ActiveState.com
------------------------------------------------------- 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