Perforce unnecessarily changes text files
I was having a terrible time with Perforce 2005.1 (and 2004.2) changing the line ending characters on my bash shell scripts, DOS batch files, and other text files. This was causing my scripts to fail in one way or another. Also, several of my PHP scripts were malfunctioning as well. Web pages I wrote that allowed users to download Excel spreadsheets were now generating a spreadsheet that contained nothing but garbage.
I then discovered, that in order for Perforce to leave the line ending characters alone, I needed to change the ClientSpec and add the files with
LineEnd: unix
and then change the ClientSpec back, and sync them with
LineEnd: share
To determine this, I wrote a small DOS batch file to analyse all possible combinations of LineEnd options, for both adding and syncing.
Here's the output from the program (edited slightly for clarity):
Add Sync file Result ------- ------- --------------- ------------------------------------- local local mac-cr.txt _ cr _ cr local local unix-lf.txt _ cr lf _ cr lf local local win-crlf.txt _ cr lf _ cr lf local mac mac-cr.txt _ cr _ cr local mac unix-lf.txt _ cr _ cr local mac win-crlf.txt _ cr _ cr local share mac-cr.txt _ cr _ cr local share unix-lf.txt _ lf _ lf local share win-crlf.txt _ lf _ lf local unix mac-cr.txt _ cr _ cr local unix unix-lf.txt _ lf _ lf local unix win-crlf.txt _ lf _ lf local win mac-cr.txt _ cr _ cr local win unix-lf.txt _ cr lf _ cr lf local win win-crlf.txt _ cr lf _ cr lf mac local mac-cr.txt _ cr lf _ cr lf mac local unix-lf.txt _ cr lf _ cr lf mac local win-crlf.txt _ cr lf cr lf _ cr lf cr lf mac mac mac-cr.txt _ cr lf _ cr lf mac mac unix-lf.txt _ cr lf _ cr lf mac mac win-crlf.txt _ cr lf cr lf _ cr lf cr lf mac share mac-cr.txt _ lf _ lf mac share unix-lf.txt _ lf _ lf mac share win-crlf.txt _ lf lf _ lf lf mac unix mac-cr.txt _ lf _ lf mac unix unix-lf.txt _ lf _ lf mac unix win-crlf.txt _ lf lf _ lf lf mac win mac-cr.txt _ cr lf _ cr lf mac win unix-lf.txt _ cr lf _ cr lf mac win win-crlf.txt _ cr lf cr lf _ cr lf cr lf share local mac-cr.txt _ cr lf _ cr lf share local unix-lf.txt _ cr lf _ cr lf share local win-crlf.txt _ cr lf _ cr lf share mac mac-cr.txt _ cr _ cr share mac unix-lf.txt _ cr _ cr share mac win-crlf.txt _ cr _ cr share share mac-cr.txt _ cr _ cr share share unix-lf.txt _ cr _ cr share share win-crlf.txt _ cr _ cr share unix mac-cr.txt _ lf _ lf share unix unix-lf.txt _ lf _ lf share unix win-crlf.txt _ lf _ lf share win mac-cr.txt _ cr lf _ cr lf share win unix-lf.txt _ cr lf _ cr lf share win win-crlf.txt _ cr lf _ cr lf unix local mac-cr.txt _ cr _ cr unix local unix-lf.txt _ cr lf _ cr lf unix local win-crlf.txt _ cr cr lf _ cr cr lf unix mac mac-cr.txt _ cr _ cr unix mac unix-lf.txt _ cr _ cr unix mac win-crlf.txt _ cr cr _ cr cr unix share mac-cr.txt _ cr _ cr unix share unix-lf.txt _ lf _ lf unix share win-crlf.txt _ cr lf _ cr lf unix unix mac-cr.txt _ cr _ cr unix unix unix-lf.txt _ cr lf _ cr lf unix unix win-crlf.txt _ cr cr lf _ cr cr lf unix win mac-cr.txt _ cr _ cr unix win unix-lf.txt _ cr lf _ cr lf unix win win-crlf.txt _ cr cr lf _ cr cr lf win local mac-cr.txt _ cr _ cr win local unix-lf.txt _ cr lf _ cr lf win local win-crlf.txt _ cr lf _ cr lf win mac mac-cr.txt _ cr _ cr win mac unix-lf.txt _ cr _ cr win mac win-crlf.txt _ cr _ cr win share mac-cr.txt _ cr _ cr win share unix-lf.txt _ lf _ lf win share win-crlf.txt _ lf _ lf win unix mac-cr.txt _ cr _ cr win unix unix-lf.txt _ lf _ lf win unix win-crlf.txt _ lf _ lf win win mac-cr.txt _ cr _ cr win win unix-lf.txt _ lf _ lf win win win-crlf.txt _ lf _ lf
And here is the program used to generate this report:
@echo off path=c:\cygwin\bin;c:\perl\bin;%path% set LINEENDS=local unix win mac share set ECHO=c:\cygwin\bin\echo.exe set PERL=c:\perl\bin\perl.exe set P4=p4.exe set OD=od.exe attrib -r *.txt del *.txt del p4test.log %P4% client -o >orig_client.p4 %P4% client -o >client.p4 for %%i in (%LINEENDS%) do ( %PERL% -p -e "s/^LineEnd:.*/LineEnd:\t%%i/g" client.p4 >client_%%i.p4 %P4% client -i <client_%%i.p4 || exit /b %ECHO% -e -n "_\r_\r" >mac-cr.txt %ECHO% -e -n "_\r\n_\r\n" >win-crlf.txt %ECHO% -e -n "_\n_\n" >unix-lf.txt %P4% add *.txt || exit /b %P4% change -o | %PERL% -e "s/enter description here/adding files with LineEnd set to %%i/" >submit_%%i.p4 %P4% submit -i <submit_%%i.p4 || exit /b for %%j in (%LINEENDS%) do ( if not "%%i" == "%%j" ( %PERL% -p -e "s/^LineEnd:.*/LineEnd:\t%%j/g" client.p4>client_%%i_%%j.p4 %P4% client -i <client_%%i_%%j.p4 || exit /b ) attrib -r *.txt del *.txt %P4% sync -f *.txt || exit /b for %%k in (*.txt) do ( %ECHO% -n -e "%%i\t%%j\t%%k\t" >>p4test.log %OD% -a %%k >>p4test.log ) ) %P4% delete *.txt || exit /b %P4% change -o | %PERL% -e "s/enter description here/deleting files with LineEnd set to %%i/" >submit_%%i_%%j.p4 %P4% submit -i <submit_%%i_%%j.p4 || exit /b ) %P4% client -i <orig_client.p4 type p4test.log
In order to run this script, you will need to have cygwin's echo.exe and od.exe (octal dump), and ActiveState perl installed.
Albert Malkin, a Perforce representative, has stated: "As I said, I've already requested that feature and linked your name to thisrequest." By "that feature", I'm assuming he is referring to my requesting that there be LineEnd option of 'none', which would leave text files alone when committed and checked out of Perforce.
- ross's blog
- Login to post comments