- <?xml version='1.0' encoding='utf-8'?>
- <!--
- This MSBuild script demonstrates the use of the P4MSBuildTasks.
- It implements the techniques described in Perforce's Technote 002 (working disconnected):
- http://www.perforce.com/perforce/technotes/note002.html
- Please read that technote, and you can see how the logic is implemented in this script.
- Many different techniques for using P4MSBuildTasks are demonstrated in this sample,
- and there are a lot of comments. It's intended to be very informative, even if you don't
- need to use the disconected method exactly.
- -->
- <Project DefaultTargets = "VerifyPerforceConnection" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
- <!-- copy the dlls to the bin folder, or update the path here.-->
- <UsingTask TaskName="P4RunCommand" AssemblyFile="bin\debug\P4MSBuildTasks.dll"/>
- <UsingTask TaskName="P4NewChangelist" AssemblyFile="bin\debug\P4MSBuildTasks.dll"/>
- <!--
- Required Variables:
- OfflineRootDirectory : Root directory to update Perforce.
- Must be in your client root.
- Variables that can be used to override Perforce Environment:
- P4PORT
- P4USER
- P4CLIENT
- P4PASSWD
- P4USELOGIN
- -->
- <PropertyGroup>
- <!-- Make P4 runs verbose. Set to false, unless debugging.-->
- <P4Verbose>false</P4Verbose>
- <!-- Changelist Description. Override if desired. -->
- <ChangelistDescription>Syncing offline work.</ChangelistDescription>
- </PropertyGroup>
- <!-- Validate Perforce's environment
- Every project that accesses Perforce should include some kind of initial verification.
- By design, errors from Perforce will NOT bubble up from P4RunCommand. So you 'should'
- check for errors after every run.
- However, in my experience, most of these errors are related to a bad
- P4PORT/P4USER/P4CLIENT or login issues. And checking these at the beginning
- of each script will usually sufice.
- -->
- <Target Name="VerifyPerforceConnection">
- <!-- Run a P4 info and verify user name and client spec-->
- <P4RunCommand Command="info" Verbose="$(P4Verbose)"
- Arguments=" "
- Client="$(P4CLIENT)" Port="$(P4PORT)" User="$(P4USER)" Password="$(P4PASSWD)" UseLogin="$(P4USELOGIN)">
- <Output TaskParameter="ParsedOutput" ItemName="P4InfoOutput"/>
- <Output TaskParameter="Errors" PropertyName="P4InfoErrors" />
- </P4RunCommand>
- <!-- Any errors means we couldn't connect to Perforce at all -->
- <Error Condition="$(P4InfoErrors)!=''" Text="Unable to Connect to Perforce!" />
- <!-- Do we have a valid User?-->
- <Error Condition="@(P4InfoOutput->'%(userName)')=='*unknown*'" Text="Perforce User is invalid!" />
- <!-- Is the client spec valid?-->
- <Error Condition="@(P4InfoOutput->'%(clientName)')=='*unknown*'" Text="Perforce Client is invalid!" />
- <!-- Unfortunately, 'p4 info' doesn't tell us if we're logged in.
- We need to run a 'p4 login -s' to find that out. -->
- <P4RunCommand Command="login" Verbose="$(P4Verbose)" Arguments="-s" Client="$(P4CLIENT)" Port="$(P4PORT)" User="$(P4USER)" Password="$(P4PASSWD)" UseLogin="$(P4USELOGIN)">
- <Output TaskParameter="Messages" PropertyName="P4LoginSOutput" />
- <Output TaskParameter="Errors" PropertyName="P4LoginSErrors" />
- <Output TaskParameter="Warnings" PropertyName="P4LoginSWarnings" />
- </P4RunCommand>
- <Message Text="Messages: $(P4LoginSOutput)" />
- <Message Text="Errors : $(P4LoginSErrors)" />
- <Message Text="Warnings: $(P4LoginSWarnings)" />
- </Target>
- <!-- Verify the required variables are set -->
- <Target Name="ValidateInputs" DependsOnTargets="VerifyPerforceConnection">
- <Error Condition="!Exists($(OfflineRootDirectory))" Text="Required variable: 'OfflineRootDirectory' is invalid, or unset!" />
- <!-- Need a trailing slash so the world is in-line. Not really validating,
- just add the backslash if necessary-->
- <CreateProperty Value="$(OfflineRootDirectory)\" Condition="!HasTrailingSlash('$(OfflineRootDirectory)')">
- <Output TaskParameter="Value" PropertyName="OfflineRootDirectory" />
- </CreateProperty>
- </Target>
- <!-- Uses 'p4 diff -se' command to find the files that need to be opened for edit-->
- <Target Name="P4FindEdits" DependsOnTargets="ValidateInputs">
- <P4RunCommand Command="diff" Verbose="$(P4Verbose)" Arguments="-se;$(OfflineRootDirectory)..." Client="$(P4CLIENT)" Port="$(P4PORT)" User="$(P4USER)" Password="$(P4PASSWD)" UseLogin="$(P4USELOGIN)">
- <Output TaskParameter="ParsedOutput" ItemName="P4ToEditOutput"/>
- </P4RunCommand>
- <!-- Filter the metadata so we have a "real" itemgroup representing the files.-->
- <CreateItem Include="@(P4ToEditOutput->'%(clientFile)')">
- <Output ItemName="FilesToEdit" TaskParameter="Include"/>
- </CreateItem>
- </Target>
- <!-- Uses 'p4 diff -sd' command to find the files that need to be opened for delete-->
- <Target Name="P4FindDeletes" DependsOnTargets="ValidateInputs">
- <P4RunCommand Command="diff" Verbose="$(P4Verbose)" Arguments="-sd;$(OfflineRootDirectory)..." Client="$(P4CLIENT)" Port="$(P4PORT)" User="$(P4USER)" Password="$(P4PASSWD)" UseLogin="$(P4USELOGIN)">
- <Output TaskParameter="ParsedOutput" ItemName="P4ToDeleteOutput"/>
- </P4RunCommand>
- <CreateItem Include="@(P4ToDeleteOutput->'%(clientFile)')">
- <Output ItemName="FilesToDelete" TaskParameter="Include"/>
- </CreateItem>
- </Target>
- <!-- Finds the files that need to be added to Perforce. The first step is to get all
- the files recursively in the folder OfflineRootDirectory. Then run
- 'p4 add -n' on that list. -->
- <Target Name="P4FindAdds" DependsOnTargets="ValidateInputs;GetAllLocalFiles">
- <!-- Notice the use of '@(AllLocalFiles)' in the Arguments. The default transformation
- for Items is to concatantate with semicolons. This is the reason Arguments are
- delimited by semicolons. -->
- <P4RunCommand Command="add" Verbose="$(P4Verbose)" Arguments="-n;@(AllLocalFiles)" Client="$(P4CLIENT)" Port="$(P4PORT)" User="$(P4USER)" Password="$(P4PASSWD)" UseLogin="$(P4USELOGIN)">
- <Output TaskParameter="ParsedOutput" ItemName="P4ToAddOutput"/>
- </P4RunCommand>
- <CreateItem Include="@(P4ToAddOutput->'%(clientFile)')">
- <Output ItemName="FilesToAdd" TaskParameter="Include"/>
- </CreateItem>
- </Target>
- <!-- Just show the files that would be affected (and how).-->
- <Target Name="Show" DependsOnTargets="P4FindAdds;P4FindDeletes;P4FindEdits">
- <Message Text="Edits:" />
- <Message Text=" %(FilesToEdit.Identity)" />
- <Message Text="Adds:" />
- <Message Text=" %(FilesToAdd.Identity)" />
- <Message Text="Deletes:" />
- <Message Text=" %(FilesToDelete.Identity)" />
- </Target>
- <!-- Creates a numbered changelist so we can get started -->
- <Target Name="CreateChangelist" DependsOnTargets="ValidateInputs">
- <P4NewChangelist ChangeDescription="$(ChangelistDescription)" Verbose="$(P4Verbose)" Client="$(P4CLIENT)" Port="$(P4PORT)" User="$(P4USER)" Password="$(P4PASSWD)" UseLogin="$(P4USELOGIN)">
- <Output TaskParameter="ChangeNumber" PropertyName="P4ChangelistNumber"/>
- </P4NewChangelist>
- <Message Text ="Change: $(P4ChangelistNumber)" />
- </Target>
- <!-- Submit's the changelist created earlier-->
- <Target Name="SubmitChangelist" DependsOnTargets="CreateChangelist" >
- <P4RunCommand Command="submit" Verbose="$(P4Verbose)"
- Arguments="-c;$(P4ChangelistNumber)"
- Client="$(P4CLIENT)" Port="$(P4PORT)" User="$(P4USER)" Password="$(P4PASSWD)" UseLogin="$(P4USELOGIN)">
- <Output TaskParameter="Messages" PropertyName="SubmitMessage"/>
- </P4RunCommand>
- <Message Text="$(SubmitMessage)" />
- </Target>
- <!-- Using the output from P4FindEdits, open that list for edit-->
- <Target Name="P4DoEdits" DependsOnTargets="CreateChangelist;P4FindEdits" >
- <P4RunCommand Command="edit" Verbose="$(P4Verbose)"
- Arguments="-c;$(P4ChangelistNumber);@(FilesToEdit)"
- Client="$(P4CLIENT)" Port="$(P4PORT)" User="$(P4USER)" Password="$(P4PASSWD)" UseLogin="$(P4USELOGIN)"
- Condition="@(FilesToEdit)!=''">
- </P4RunCommand>
- </Target>
- <!-- Using the output from P4FindDeletes, open that list for delete-->
- <!-- Note the condition on the task. This is important, b/c if there are no files to delete,
- then the p4 delete command that's generated is invalid. -->
- <Target Name="P4DoDeletes" DependsOnTargets="P4FindDeletes;CreateChangelist">
- <P4RunCommand Command="delete" Verbose="$(P4Verbose)"
- Arguments="-c;$(P4ChangelistNumber);@(FilesToDelete);"
- Client="$(P4CLIENT)" Port="$(P4PORT)" User="$(P4USER)" Password="$(P4PASSWD)" UseLogin="$(P4USELOGIN)"
- Condition="@(FilesToDelete)!=''" />
- </Target>
- <!-- Add all local files to P4 (it will warn on files that already exist... but who cares :-) -->
- <!-- Note, we don't depend on P4FindAdds. There's no reason, since P4FindAdds runs
- an 'add -n', and we're just going to run a standard 'add' -->
- <Target Name="P4DoAdds" DependsOnTargets="CreateChangelist;GetAllLocalFiles">
- <P4RunCommand Command="add" Verbose="$(P4Verbose)"
- Arguments="-c;$(P4ChangelistNumber);@(AllLocalFiles)"
- Client="$(P4CLIENT)" Port="$(P4PORT)" User="$(P4USER)" Password="$(P4PASSWD)" UseLogin="$(P4USELOGIN)">
- <Output TaskParameter="ParsedOutput" ItemName="P4ToAddOutput"/>
- </P4RunCommand>
- <CreateItem Include="@(P4ToAddOutput->'%(clientFile)')">
- <Output ItemName="FilesToAdd" TaskParameter="Include"/>
- </CreateItem>
- </Target>
- <!-- Main Target. Will process Adds, Edits, and Deletes -->
- <!-- Will NOT submit the pending changelist -->
- <Target Name="WorkOffline" DependsOnTargets="P4DoAdds;P4DoDeletes;P4DoEdits">
- </Target>
- <!-- WILL submit the pending changelist after WorkOffline. -->
- <Target Name="WorkOfflineAndSubmit" DependsOnTargets="WorkOffline;SubmitChangelist">
- </Target>
- <!-- Dynamically create the itemgroup containing all the files (recursively)
- in OfflineRootDirectory -->
- <Target Name="GetAllLocalFiles">
- <CreateItem Include="$(OfflineRootDirectory)**\*.*">
- <Output ItemName="AllLocalFiles" TaskParameter="Include"/>
- </CreateItem>
- </Target>
- </Project>
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 7889 | Johan Nilsson | Branch from Shawn Hladky's original P4.Net (main branch). Changed file type for StandardT...est.cs and UnicodeTest.cs in order to be able to check them in. « |
14 years ago | |
//guest/shawn_hladky/P4.Net/main/samples/P4MSBuildTasks/src/P4MSBuildTasks/WorkingOffline.proj | |||||
#1 | 5830 | Shawn Hladky | P4.Net: reorg to support release branches | 18 years ago | |
//guest/shawn_hladky/P4.Net/samples/P4MSBuildTasks/src/P4MSBuildTasks/WorkingOffline.proj | |||||
#2 | 5820 | Shawn Hladky | P4.Net: splitting samples to thier own solution files | 18 years ago | |
#1 | 5812 | Shawn Hladky | P4.Net: More documentation. | 18 years ago |