m_sContent = ''; } public final function mGet() { $r_h_mMap = array(); $l_sSection = null; foreach (explode("\n", str_replace(array("\r\n", "\r"), "\n", $this->m_sContent)) as $l_sLine) { $l_sLine = trim($l_sLine); if ('' === $l_sLine) { $l_sSection = null; } else { if (('[' === $l_sLine[0]) && (substr($l_sLine, -1) === ']')) { $l_sSection = substr($l_sLine, 1, -1); assert('!array_key_exists($l_sSection, $r_h_mMap)'); $r_h_mMap[$l_sSection] = array(); } else { $l_iPosition = strpos($l_sLine, '='); assert('false !== $l_iPosition'); assert('0 !== $l_iPosition'); $l_sKey = trim(substr($l_sLine, 0, $l_iPosition)); $l_sValue = trim(substr($l_sLine, $l_iPosition + 1)); if (null === $l_sSection) { assert('!array_key_exists($l_sKey, $r_h_mMap)'); $r_h_mMap[$l_sKey] = $l_sValue; } else { assert('!array_key_exists($l_sKey, $r_h_mMap[$l_sSection])'); $r_h_mMap[$l_sSection][$l_sKey] = $l_sValue; } } } } return $r_h_mMap; } public final function mRead($a_sData) { $this->m_sContent .= $a_sData; } } final class cIniWriter { private $m_sContent; public final function __construct() { $this->m_sContent = ''; } public final function mGet() { return $this->m_sContent; } public final function mWrite($a_h_mData) { assert('is_array($a_h_mData)'); $l_a_sSectionList = array_keys($a_h_mData); natsort($l_a_sSectionList); $l_bFirst = true; foreach ($l_a_sSectionList as $l_sSection) { if (!is_array($a_h_mData[$l_sSection])) { $l_bFirst = false; $this->m_sContent .= $l_sSection.'='.$a_h_mData[$l_sSection].PHP_EOL; } } foreach ($l_a_sSectionList as $l_sSection) { if (is_array($a_h_mData[$l_sSection])) { if (true === $l_bFirst) { $l_bFirst = false; } else { $this->m_sContent .= PHP_EOL; } $this->m_sContent .= '['.$l_sSection.']'.PHP_EOL; $l_a_sKeyList = array_keys($a_h_mData[$l_sSection]); natsort($l_a_sKeyList); foreach ($l_a_sKeyList as $l_sKey) { $this->m_sContent .= $l_sKey.'='.$a_h_mData[$l_sSection][$l_sKey].PHP_EOL; } } } } } if (!function_exists('fnmatch')) { function fnmatch($a_sPattern, $a_sText) { return @preg_match('/^'.strtr(addcslashes($a_sPattern, '/\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')).'$/', $a_sText); } } function gAssert($a_sFile, $a_iLine, $a_sMessage) { echo PHP_EOL, $a_sFile, PHP_EOL, 'Assertion failed at line ', $a_iLine, PHP_EOL, $a_sMessage, PHP_EOL; die(2); } function gAssertFileFormatIni($a_sFile, $a_iLine, $a_sMessage) { throw new Exception(); } function gAttributeList($a_sPath) { return str_split(str_replace(' ', '', substr(gCommand('"'.$_ENV['attrib'].'" "'.$a_sPath.'"'), 0, 13))); } function gAttributeSet($a_sPath, $a_a_sList) { gCommand('"'.$_ENV['attrib'].'" +'.implode(' -', $a_a_sList).' "'.$a_sPath.'"'); } function gAttributeUnset($a_sPath, $a_a_sList) { gCommand('"'.$_ENV['attrib'].'" -'.implode(' -', $a_a_sList).' "'.$a_sPath.'"'); } function gCommand($a_sCommand) { $l_sCommand = $a_sCommand.' 2>&1'; gLog($l_sCommand.PHP_EOL); ob_start(); passthru($l_sCommand); $r_sLog = ob_get_contents(); ob_end_clean(); gLog($r_sLog); return $r_sLog; } function gCompare($a_sFirst, $a_sSecond) { $r_iCompare = strcasecmp($a_sFirst, $a_sSecond); if (0 === $r_iCompare) { return strcmp($a_sFirst, $a_sSecond); } else { return $r_iCompare; } } function gDisplayPath($a_sPath) { global $g_iPathLength; echo iconv('Cp1252', 'UTF-8//TRANSLIT', substr($a_sPath, $g_iPathLength)), PHP_EOL; } function gError($a_iError, $a_sError, $a_sFile, $a_iLine, $a_h_mContext) { if (!((2 === $a_iError) && ('fopen(' === substr($a_sError, 0, 6)) && ((': failed to open stream: Invalid argument' === substr($a_sError, -41)) || ('): failed to open stream: No error' === substr($a_sError, -34))) && (__FILE__ === $a_sFile) && (242 === $a_iLine))) { echo PHP_EOL, $a_sFile, PHP_EOL, 'Error ', $a_sError, ' (', $a_iError, ') at line ', $a_iLine, PHP_EOL; die(3); } } function gFormatPath($a_sPath) { static $s_sPath, $s_iTrim; if (null === $s_sPath) { $s_sPath = realpath(getcwd()); if (DIRECTORY_SEPARATOR !== substr($s_sPath, -strlen(DIRECTORY_SEPARATOR))) { $s_sPath .= DIRECTORY_SEPARATOR; } $s_iTrim = strlen($s_sPath); } if ($s_sPath === substr($a_sPath, 0, $s_iTrim)) { return substr($a_sPath, $s_iTrim); } else { return $a_sPath; } } function gLog($a_sMessage) { static $s_rFile; if (null === $s_rFile) { $s_rFile = fopen(substr(__FILE__, 0, -3).'log', 'wb'); } fputs($s_rFile, $a_sMessage); } function gNormalizeDirectory($a_sPath) { $l_a_sIgnoreList = explode(' ', '. .. .svn desktop.ini thumbs.db'); $l_sPath = substr($a_sPath, 0, -1); $l_h_sPropertyMap = gPropertyMapGet($l_sPath); if (is_array($l_h_sPropertyMap)) { $l_a_sChildList = scandir($a_sPath); $l_h_a_sPropertyMapSource = array(); foreach ($l_h_sPropertyMap as $l_sKey => $l_sValue) { foreach (array_map('trim', explode(PHP_EOL, $l_sValue)) as $l_sValue) { if ('' !== $l_sValue) { $l_h_a_sPropertyMapSource[$l_sKey][] = $l_sValue; } } } $l_h_a_sPropertyMapTarget = $l_h_a_sPropertyMapSource; foreach ($l_a_sChildList as $l_sChildName) { if (!in_array(strtolower($l_sChildName), $l_a_sIgnoreList, true)) { $l_sChildPath = $a_sPath.$l_sChildName; if (is_dir($l_sChildPath)) { gNormalizeDirectory($l_sChildPath.DIRECTORY_SEPARATOR); } else { gNormalizeFile($l_sChildPath); if ('.chm' === substr($l_sChildPath, -4)) { $l_h_a_sPropertyMapTarget['svn:ignore'][] = '*.chw'; } else if ('.py' === substr($l_sChildPath, -3)) { $l_h_a_sPropertyMapTarget['svn:ignore'][] = '__pycache__'; $l_h_a_sPropertyMapTarget['svn:ignore'][] = '*.pyc'; $l_h_a_sPropertyMapTarget['svn:ignore'][] = '*.pyo'; } } } } $l_h_a_sPropertyMapTarget = gNormalizeProperty($l_h_a_sPropertyMapTarget); if ($l_h_a_sPropertyMapTarget !== $l_h_a_sPropertyMapSource) { gDisplayPath($a_sPath); foreach ($l_h_a_sPropertyMapTarget as $l_sKey => $l_a_sValueList) { gPropertyValueSet($l_sPath, $l_sKey, implode(PHP_EOL, $l_a_sValueList)); } } } } function gNormalizeFile($a_sPath) { static $s_a_sBinaryList, $s_a_h_mDetectionList, $s_h2_sPropertyMap, $s_a_sTextList; if (null === $s_a_sBinaryList) { $s_a_sBinaryList = array(); $s_a_h_mDetectionList = array(); $s_h2_sPropertyMap = array(); $s_a_sTextList = array(); $l_h_mDetectionMap = array(); $l_sPatternFile = '[A-Za-z0-9 .*_-]+'; $l_sPatternKey = '[a-z:-]+'; $l_sPatternValue = '[A-Za-z0-9.*\/+-]+'; $l_sSection = ''; foreach (array_map('trim', explode("\n", str_replace(array("\r\n", "\r"), "\n", file_get_contents(substr(__FILE__, 0, -3).'cfg')))) as $l_sLine) { if (('' !== $l_sLine) && ('#' !== $l_sLine[0])) { if (1 === preg_match('/^\[[a-z-]+\]$/', $l_sLine)) { $l_sSection = $l_sLine; } else if ('[auto-props-heuristics]' === $l_sSection) { if ('prop ' === substr($l_sLine, 0, 5)) { $l_h_mDetectionMap['prop'] = gPropertyExplode(substr($l_sLine, 5), 'block', $s_a_sBinaryList, $s_a_sTextList); $s_a_h_mDetectionList[] = $l_h_mDetectionMap; $l_h_mDetectionMap = array(); } else if (1 === preg_match('/^[a-z]{4} /', $l_sLine)) { $l_h_mDetectionMap[substr($l_sLine, 0, 4)] = substr($l_sLine, 5); } else { echo PHP_EOL, 'Unknown "', $l_sLine, '" line format', PHP_EOL, PHP_EOL; die(4); } } else if ('[auto-props]' === $l_sSection) { if (1 === preg_match('/^('.$l_sPatternFile.')\s*=((?:\s*'.$l_sPatternKey.'\s*=\s*'.$l_sPatternValue.'\s*;?)+)$/', $l_sLine, $l_a_sMatchList)) { $s_h2_sPropertyMap[trim($l_a_sMatchList[1])] = gPropertyExplode($l_a_sMatchList[2], '"'.$l_a_sMatchList[1].'"', $s_a_sBinaryList, $s_a_sTextList); } else { echo PHP_EOL, 'Unknown "', $l_sLine, '" line format', PHP_EOL, PHP_EOL; die(5); } } else if ('[auto-props-binary]' === $l_sSection) { $s_a_sBinaryList[] = $l_sLine; } else if ('[auto-props-text]' === $l_sSection) { $s_a_sTextList[] = $l_sLine; } } } } gDisplayPath($a_sPath); $l_sName = strtolower(basename($a_sPath)); echo '- reading header', PHP_EOL; $l_bBinary = null; $l_rFile = @fopen($a_sPath, 'rb'); if (is_resource($l_rFile)) { echo '- detecting type', PHP_EOL; $l_bBinary = false; $l_a_iCharacterList = array ( 0x00, 0x09, 0x0A, 0x0C, 0x0D, 0x1A, ); for ($l_iOffset = 0; !feof($l_rFile); $l_iOffset += 4096) { assert('ftell($l_rFile) === $l_iOffset'); $l_sBlock = fread($l_rFile, 4096); if (0 === $l_iOffset) { $l_sHeader = $l_sBlock; } $l_iSize = strlen($l_sBlock); for ($l_iPosition = 0; $l_iSize !== $l_iPosition; ++$l_iPosition) { $l_iCharacter = ord($l_sBlock[$l_iPosition]); if (($l_iCharacter < 32) && !in_array($l_iCharacter, $l_a_iCharacterList)) { echo ' found character 0x', sprintf('%02X', $l_iCharacter), ' at ', ($l_iOffset + $l_iPosition), PHP_EOL; $l_bBinary = true; break 2; } } } fclose($l_rFile); echo '- detecting format', PHP_EOL; foreach ($s_a_h_mDetectionList as $l_h_mDetectionMap) { foreach ($l_h_mDetectionMap as $l_sKey => $l_mValue) { if ('find' === $l_sKey) { assert('is_string($l_mValue)'); if (1 !== preg_match($l_mValue, $l_sHeader)) { break; } } else if ('name' === $l_sKey) { assert('is_string($l_mValue)'); if (!fnmatch($l_mValue, $l_sName)) { break; } } else if ('prop' === $l_sKey) { assert('is_array($l_mValue)'); echo ' found ', $l_h_mDetectionMap['desc'], PHP_EOL; gPropertyMapSet($a_sPath, $l_mValue); return; } else if ('desc' !== $l_sKey) { echo PHP_EOL, 'Unknown "', $l_sKey, '" detection key', PHP_EOL, PHP_EOL; die(6); } } } } echo '- detecting property', PHP_EOL; foreach ($s_h2_sPropertyMap as $l_sPattern => $l_h_sPropertyMap) { if (fnmatch($l_sPattern, $l_sName)) { echo ' matched ', $l_sPattern, PHP_EOL; if (true === $l_bBinary) { if (!array_key_exists('svn:eol-style', $l_h_sPropertyMap)) { gPropertyMapSet($a_sPath, $l_h_sPropertyMap); return; } } else { if (false === $l_bBinary) { assert(!array_key_exists('svn:needs-lock', $l_h_sPropertyMap)); $l_h_sPropertyMap['svn:needs-lock'] = ''; } gPropertyMapSet($a_sPath, $l_h_sPropertyMap); if (array_key_exists('svn:eol-style', $l_h_sPropertyMap)) { gNormalizeFileEol($a_sPath, $l_h_sPropertyMap['svn:eol-style']); } if ('.ini' === substr($l_sName, -4)) { gNormalizeFileFormatIni($a_sPath); } else { if (array_key_exists('svn:mime-type', $l_h_sPropertyMap)) { $l_sType = $l_h_sPropertyMap['svn:mime-type']; if ('text/x-url' === $l_sType) { gNormalizeFileFormatIni($a_sPath); } } } return; } } } echo '- using heuristics', PHP_EOL; if ($l_bBinary) { echo ' binary mode', PHP_EOL; gPropertyMapSet($a_sPath, array ( 'svn:eol-style' => '', 'svn:mime-type' => 'application/octet-stream', 'svn:needs-lock' => '*', )); } else { echo ' text mode', PHP_EOL; gPropertyMapSet($a_sPath, array ( 'svn:eol-style' => 'native', 'svn:mime-type' => 'text/plain', 'svn:needs-lock' => '', )); gNormalizeFileEol($a_sPath, 'native'); } } function gNormalizeFileEol($a_sPath, $a_sEol) { echo '- converting EOL to ', $a_sEol, PHP_EOL; $l_sContent = file_get_contents($a_sPath); if ('CR' === $a_sEol) { $l_sContentEol = str_replace("\r\n", "\r", $l_sContent); $l_sContentEol = str_replace("\n", "\r", $l_sContentEol); } else { $l_sContentEol = str_replace("\r\n", "\n", $l_sContent); $l_sContentEol = str_replace("\r", "\n", $l_sContentEol); if ('CRLF' === $a_sEol) { $l_sContentEol = str_replace("\n", "\r\n", $l_sContentEol); } else if ('native' === $a_sEol) { $l_sContentEol = str_replace("\n", PHP_EOL, $l_sContentEol); } } if ($l_sContent !== $l_sContentEol) { gWrite($a_sPath, $l_sContentEol); } } function gNormalizeFileFormatIni($a_sPath) { echo '- normalizing INI format', PHP_EOL; assert_options(ASSERT_BAIL, 0); assert_options(ASSERT_CALLBACK, 'gAssertFileFormatIni'); try { $l_oReader = new cIniReader(); $l_oReader->mRead(file_get_contents($a_sPath)); $l_h2_sMap = $l_oReader->mGet(); $l_oWriter = new cIniWriter(); $l_oWriter->mWrite($l_h2_sMap); gWrite($a_sPath, $l_oWriter->mGet()); } catch (Exception $l_eException) { echo '- unsupported INI format', PHP_EOL; } assert_options(ASSERT_BAIL, 1); assert_options(ASSERT_CALLBACK, 'gAssert'); } function gNormalizeProperty($a_h_a_sPropertyMap) { $r_h_a_sPropertyMap = array(); $l_a_sKeyList = array_keys($a_h_a_sPropertyMap); usort($l_a_sKeyList, 'gCompare'); foreach ($l_a_sKeyList as $l_sKey) { $l_a_sValueList = array_unique($a_h_a_sPropertyMap[$l_sKey]); if ('svn:externals' === $l_sKey) { $l_h_sValueMap = array(); foreach ($l_a_sValueList as $l_iValue => $l_sValue) { $l_a_sArgumentList = explode(' ', $l_sValue); $l_iArgumentCount = count($l_a_sArgumentList); $l_iRevision = null; $l_sSource = null; $l_sTarget = null; for ($l_iArgumentIndex = 0; $l_iArgumentCount !== $l_iArgumentIndex; ++$l_iArgumentIndex) { $l_sArgument = $l_a_sArgumentList[$l_iArgumentIndex]; if ((null === $l_iRevision) && ('-r' === $l_sArgument) && ($l_iArgumentIndex + 1 !== $l_iArgumentCount) && (1 === preg_match('/^[0-9]+$/', $l_a_sArgumentList[$l_iArgumentIndex + 1]))) { ++$l_iArgumentIndex; $l_iRevision = (int)($l_a_sArgumentList[$l_iArgumentIndex]); } else { if ((null === $l_sSource) && (('file:///' === substr($l_sArgument, 0, 8)) || ('http://' === substr($l_sArgument, 0, 7)) || ('https://' === substr($l_sArgument, 0, 8)) || ('svn://' === substr($l_sArgument, 0, 6)) || ('svn+ssh://' === substr($l_sArgument, 0, 10)) || ('../' === substr($l_sArgument, 0, 3)) || ('^/' === substr($l_sArgument, 0, 2)) || ('//' === substr($l_sArgument, 0, 2)) || ('/' === $l_sArgument[0]))) { $l_sSource = $l_sArgument; if ((null === $l_iRevision) && (1 === preg_match('/@([0-9]+)$/', $l_sSource, $l_a_sMatchList))) { $l_iRevision = (int)($l_a_sMatchList[1]); $l_sSource = substr($l_sSource, 0, -(strlen($l_iRevision) + 1)); } } else { if (null === $l_sTarget) { $l_sTarget = $l_sArgument; } else { $l_sTarget .= ' '.$l_sArgument; } } } } if ((null !== $l_sSource) && (null !== $l_sTarget)) { if (('"' === $l_sTarget[0]) && ('"' === substr($l_sTarget, -1))) { $l_sTarget = substr($l_sTarget, 1, -1); } else if (('\'' === $l_sTarget[0]) && ('\'' === substr($l_sTarget, -1))) { $l_sTarget = substr($l_sTarget, 1, -1); } if (null === $l_iRevision) { $l_h_sValueMap[$l_sTarget] = $l_sSource; } else { $l_h_sValueMap[$l_sTarget] = $l_sSource.'@'.$l_iRevision; } } } uksort($l_h_sValueMap, 'gCompare'); $l_a_sValueList = array(); foreach ($l_h_sValueMap as $l_sTarget => $l_sSource) { if (false !== strpos($l_sTarget, ' ')) { $l_sTarget = '"'.$l_sTarget.'"'; } $l_a_sValueList[] = $l_sSource.' '.$l_sTarget; } } else { if ('svn:ignore' === $l_sKey) { foreach ($l_a_sValueList as $l_sValue) { if ('.ipa' === substr($l_sValue, -4)) { $l_a_sValueList[] = substr($l_sValue, 0, -4); } } $l_a_sValueList = array_unique($l_a_sValueList); } usort($l_a_sValueList, 'gCompare'); } $r_h_a_sPropertyMap[$l_sKey] = $l_a_sValueList; } return $r_h_a_sPropertyMap; } function gPropertyExplode($a_sLine, $a_sDescription, $a_a_sBinaryList, $a_a_sTextList) { $l_sPatternKey = '[a-z:-]+'; $l_sPatternValue = '[A-Za-z0-9.*\/+-]+'; if (1 <= preg_match_all('/('.$l_sPatternKey.')\s*=\s*('.$l_sPatternValue.')/', $a_sLine, $l_a2_sMatchList)) { $r_h_sMap = array_combine($l_a2_sMatchList[1], $l_a2_sMatchList[2]); if (array_key_exists('svn:mime-type', $r_h_sMap)) { if (in_array($r_h_sMap['svn:mime-type'], $a_a_sTextList, true) || ('text/' === substr($r_h_sMap['svn:mime-type'], 0, 5)) || ('+xml' === substr($r_h_sMap['svn:mime-type'], -4))) { if (array_key_exists('svn:eol-style', $r_h_sMap)) { if (!in_array($r_h_sMap['svn:eol-style'], explode(' ', 'CR CRLF LF native'), true)) { echo PHP_EOL, $a_sDescription, ' defines an unknown "', $r_h_sMap['svn:eol-style'], '" EOL style', PHP_EOL, PHP_EOL; die(7); } } else { echo PHP_EOL, $a_sDescription, ' implies "', $r_h_sMap['svn:mime-type'], '" MIME type but no EOL style', PHP_EOL, PHP_EOL; die(8); } } else if (in_array(substr($r_h_sMap['svn:mime-type'], 0, strpos($r_h_sMap['svn:mime-type'], '/')), $a_a_sBinaryList, true)) { if (array_key_exists('svn:needs-lock', $r_h_sMap)) { if ('false' === $r_h_sMap['svn:needs-lock']) { $r_h_sMap['svn:needs-lock'] = ''; } else { $r_h_sMap['svn:needs-lock'] = '*'; } } else { echo PHP_EOL, $a_sDescription, ' implies "', $r_h_sMap['svn:mime-type'], '" MIME type but does not require lock', PHP_EOL, PHP_EOL; die(9); } } else { echo PHP_EOL, $a_sDescription, ' defines an unknown "', $r_h_sMap['svn:mime-type'], '" MIME type', PHP_EOL, PHP_EOL; die(10); } } else { echo PHP_EOL, $a_sDescription, ' does not define a MIME type', PHP_EOL, PHP_EOL; die(11); } return $r_h_sMap; } else { echo PHP_EOL, 'Unknown "', $a_sLine, '" property format', PHP_EOL, PHP_EOL; die(12); } } function gPropertyKeyList($a_sPath) { $l_sCommand = 'proplist "'.$a_sPath.'@"'; $l_sLog = gSubversion($l_sCommand); $r_a_sList = array(); if ('' !== $l_sLog) { $l_sLogExpected = 'Properties on \''.$a_sPath.'\':'.PHP_EOL; $l_iLogExpectedLength = strlen($l_sLogExpected); if ($l_sLogExpected === substr($l_sLog, 0, $l_iLogExpectedLength)) { foreach (array_map('trim', explode(PHP_EOL, substr($l_sLog, $l_iLogExpectedLength))) as $l_sKey) { if ('' !== $l_sKey) { $r_a_sList[] = $l_sKey; } } usort($r_a_sList, 'gCompare'); } else { gLog($l_sLogExpected); echo PHP_EOL, $l_sCommand, PHP_EOL, PHP_EOL, $l_sLog, PHP_EOL, $l_sLogExpected, PHP_EOL, PHP_EOL; die(13); } } return $r_a_sList; } function gPropertyMapGet($a_sPath) { $r_h_sPropertyMap = array(); $l_sCommand = 'proplist --verbose "'.$a_sPath.'@"'; $l_sLog = gSubversion($l_sCommand); if ('' !== $l_sLog) { $l_sLogExpected = 'Properties on \''.$a_sPath.'\':'.PHP_EOL; $l_iLogExpectedLength = strlen($l_sLogExpected); if ($l_sLogExpected === substr($l_sLog, 0, $l_iLogExpectedLength)) { $l_sKey = null; foreach (explode(PHP_EOL, substr($l_sLog, $l_iLogExpectedLength)) as $l_sLine) { if ('' !== trim($l_sLine)) { if (' ' === substr($l_sLine, 0, 2)) { if (' ' === substr($l_sLine, 0, 4)) { if (null !== $l_sKey) { $l_sLine = trim($l_sLine); $l_sLineUtf8 = iconv('Cp850', 'UTF-8', $l_sLine); if ($l_sLine === iconv('UTF-8', 'Cp850//TRANSLIT', $l_sLineUtf8)) { $l_sLine = $l_sLineUtf8; } $r_h_sPropertyMap[$l_sKey] .= $l_sLine.PHP_EOL; } } else { $l_sKey = trim($l_sLine); $r_h_sPropertyMap[$l_sKey] = ''; } } } } uksort($r_h_sPropertyMap, 'gCompare'); } else if ('svn: warning: W200005: \''.$a_sPath.'\' is not under version control'.PHP_EOL.'svn: E200009: Could not display properties of all targets because some targets are not versioned'.PHP_EOL.'svn: E200009: Illegal target for the requested operation'.PHP_EOL === $l_sLog) { return; } else { gLog($l_sLogExpected); echo PHP_EOL, $l_sCommand, PHP_EOL, PHP_EOL, $l_sLog, PHP_EOL, $l_sLogExpected, PHP_EOL, PHP_EOL; die(14); } } return $r_h_sPropertyMap; } function gPropertyMapSet($a_sPath, $a_h_sPropertyMap) { foreach ($a_h_sPropertyMap as $l_sKey => $l_sValue) { gPropertyValueSet($a_sPath, $l_sKey, $l_sValue); } } function gPropertyValueGet($a_sPath, $a_sKey) { $l_sPath = preg_replace_callback('/^(\\\\\\\\[A-Z0-9]+\\\\)/', 'strtolower', $a_sPath); $l_sCommand = 'propget "'.$a_sKey.'" "'.$a_sPath.'@"'; $l_sLog = gSubversion($l_sCommand); if ('' === $l_sLog) { echo PHP_EOL, $l_sCommand, PHP_EOL, PHP_EOL, $l_sLog, PHP_EOL, PHP_EOL; die(15); } else { return $l_sLog; } } function gPropertyValueSet($a_sPath, $a_sKey, $a_sValue) { $l_sPath = preg_replace_callback('/^(\\\\\\\\[A-Z0-9]+\\\\)/', 'strtolower', $a_sPath); $l_sValue = str_replace(array("\r\n", "\r"), "\n", $a_sValue); if ('' === $l_sValue) { echo '- unset ', $a_sKey, PHP_EOL; } else { foreach (explode("\n", $l_sValue) as $l_sLine) { echo '- set ', $a_sKey, ' = ', $l_sLine, PHP_EOL; } } if ('*' === $a_sValue) { $l_sValue = 'on'; } $l_sLogExpected = ''; $l_sWarningExpected = ''; if ('' === $l_sValue) { $l_sFile = null; $l_sCommand = 'propdel "'.$a_sKey.'" "'.$l_sPath.'@"'; $l_sLogExpected = 'property \''.$a_sKey.'\' deleted from \''.gFormatPath($l_sPath).'\'.'.PHP_EOL; } else { if (false === strpos($l_sValue, "\n")) { $l_sFile = null; $l_sCommand = 'propset --encoding=UTF-8 --force "'.$a_sKey.'" "'.str_replace('"', '\\"', $l_sValue).'" "'.$l_sPath.'@"'; } else { $l_sFile = substr(__FILE__, 0, -3).'txt'; gWrite($l_sFile, str_replace("\n", PHP_EOL, $l_sValue)); $l_sCommand = 'propset --encoding=UTF-8 --file "'.$l_sFile.'" --force "'.$a_sKey.'" "'.$l_sPath.'@"'; } $l_sLogExpected = 'property \''.$a_sKey.'\' set on \''.gFormatPath($l_sPath).'\''.PHP_EOL; if ('svn:mime-type' === $a_sKey) { $l_sWarningExpected = 'svn: warning: \''.$a_sValue.'\' is a binary mime-type but file \''.$a_sPath.'\' looks like text; diff, merge, blame, and other operations will stop working on this file'.PHP_EOL; } } $l_sLog = gSubversion($l_sCommand); if (($l_sLogExpected !== $l_sLog) && ($l_sWarningExpected.$l_sLogExpected !== $l_sLog)) { if ('' !== $l_sWarningExpected) { gLog($l_sWarningExpected); $l_iWarningExpectedLength = strlen($l_sWarningExpected); if (substr($l_sLog, 0, $l_iWarningExpectedLength) === $l_sWarningExpected) { $l_sLog = substr($l_sLog, $l_iWarningExpectedLength); } } gLog($l_sLogExpected); if ('\''.gFormatPath($a_sPath).'\' is not under version control'.PHP_EOL.'svn: E155010: The node \''.$a_sPath.'\' was not found.'.PHP_EOL === $l_sLog) { echo ' not under version control, not found', PHP_EOL; return; } else if ('\''.gFormatPath($a_sPath).'\' is not under version control'.PHP_EOL.'svn: E155023: Can\'t set properties on \''.$a_sPath.'\': invalid status for updating properties.'.PHP_EOL === $l_sLog) { echo ' not under version control, invalid status', PHP_EOL; return; } else if ('Attempting to delete nonexistent property \''.$a_sKey.'\' on \''.gFormatPath($a_sPath).'\''.PHP_EOL === $l_sLog) { echo ' already clear', PHP_EOL; return; } else { echo PHP_EOL, $l_sCommand, PHP_EOL, PHP_EOL, $l_sLog, PHP_EOL, $l_sLogExpected, PHP_EOL, PHP_EOL; die(16); } } if (null !== $l_sFile) { unlink($l_sFile); } gLog(PHP_EOL); } function gSubversion($a_sCommand) { return gCommand('"'.$_ENV['svn'].'" '.$a_sCommand); } function gWrite($a_sPath, $a_sContent) { restore_error_handler(); $l_rHandle = @fopen($a_sPath, 'wb'); set_error_handler('gError'); if (!is_resource($l_rHandle)) { $l_a_sAttributeList = gAttributeList($a_sPath); if (!empty($l_a_sAttributeList)) { gAttributeUnset($a_sPath, $l_a_sAttributeList); $l_rHandle = fopen($a_sPath, 'wb'); gAttributeSet($a_sPath, $l_a_sAttributeList); } } fwrite($l_rHandle, $a_sContent); fclose($l_rHandle); } $g_sPath = dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR; $g_sPathIni = $g_sPath.'tool'.DIRECTORY_SEPARATOR.'ini'.DIRECTORY_SEPARATOR; if (array_key_exists(1, $_SERVER['argv'])) { $g_sPath = realpath($_SERVER['argv'][1]); if (DIRECTORY_SEPARATOR !== substr($g_sPath, -strlen(DIRECTORY_SEPARATOR))) { $g_sPath .= DIRECTORY_SEPARATOR; } } $g_iPathLength = strlen($g_sPath); if (is_dir($g_sPath)) { gNormalizeDirectory($g_sPath); } else { echo 'Usage: "', basename(__FILE__), '" "path to normalize"', PHP_EOL; die(1); } ?>