Added new POpen with windows support since windows builtin _popen pops up a window on each call which is not acceptable. Removed a bunch of warnings as well.
This commit is contained in:
Родитель
d6a5621966
Коммит
2942f8a04b
|
@ -33,6 +33,18 @@ void ConvertUnityPathName( const char* utf8, wchar_t* outBuffer, int outBufferSi
|
|||
ConvertSeparatorsToWindows( outBuffer );
|
||||
}
|
||||
|
||||
string PluginPath()
|
||||
{
|
||||
HMODULE hModule = GetModuleHandleW(NULL);
|
||||
if (hModule == NULL)
|
||||
return "";
|
||||
|
||||
CHAR path[MAX_PATH];
|
||||
if (GetModuleFileNameA(hModule, path, MAX_PATH) == 0)
|
||||
return "";
|
||||
return path;
|
||||
}
|
||||
|
||||
const size_t kDefaultPathBufferSize = 1024;
|
||||
|
||||
bool EnsureDirectory(const string& path)
|
||||
|
@ -78,14 +90,14 @@ bool IsDirectory(const string& path)
|
|||
{
|
||||
wchar_t widePath[kDefaultPathBufferSize];
|
||||
ConvertUnityPathName(path.c_str(), widePath, kDefaultPathBufferSize);
|
||||
return PathIsDirectoryW(widePath);
|
||||
return PathIsDirectoryW(widePath) == TRUE;
|
||||
}
|
||||
|
||||
bool PathExists(const std::string& path)
|
||||
{
|
||||
wchar_t widePath[kDefaultPathBufferSize];
|
||||
ConvertUnityPathName(path.c_str(), widePath, kDefaultPathBufferSize);
|
||||
return PathFileExistsW(widePath);
|
||||
return PathFileExistsW(widePath) == TRUE;
|
||||
}
|
||||
|
||||
static bool RemoveReadOnlyW(LPCWSTR path)
|
||||
|
|
|
@ -13,4 +13,5 @@ bool PathExists(const std::string& path);
|
|||
#if WIN32
|
||||
#include "windows.h"
|
||||
void ConvertUnityPathName( const char* utf8, wchar_t* outBuffer, int outBufferSize );
|
||||
std::string PluginPath();
|
||||
#endif
|
||||
|
|
|
@ -23,11 +23,16 @@ LogWriter& Endl(LogWriter& w)
|
|||
|
||||
LogStream::LogStream(const std::string& path, LogLevel level)
|
||||
: m_Stream(path.c_str(), std::ios_base::ate),
|
||||
m_OnWriter(*this, true),
|
||||
m_OffWriter(*this, false)
|
||||
m_OnWriter(Self(), true),
|
||||
m_OffWriter(Self(), false)
|
||||
{
|
||||
}
|
||||
|
||||
LogStream& LogStream::Self(void)
|
||||
{
|
||||
// Work around C4355
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogStream::~LogStream()
|
||||
{
|
||||
|
|
|
@ -55,6 +55,8 @@ class LogStream
|
|||
public:
|
||||
LogStream(const std::string& path, LogLevel level = LOG_NOTICE);
|
||||
~LogStream();
|
||||
|
||||
LogStream& Self(void);
|
||||
|
||||
void SetLogLevel(LogLevel l);
|
||||
LogLevel GetLogLevel() const;
|
||||
|
|
|
@ -0,0 +1,297 @@
|
|||
#include "Utility.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
#include "string.h"
|
||||
#include "FileSystem.h"
|
||||
|
||||
#define BUFSIZE 4096
|
||||
|
||||
POpen::POpen(const string& cmd) : m_Command(cmd)
|
||||
, m_ChildStd_IN_Rd(NULL)
|
||||
, m_ChildStd_IN_Wr(NULL)
|
||||
, m_ChildStd_OUT_Rd(NULL)
|
||||
, m_ChildStd_OUT_Wr(NULL)
|
||||
, m_BufSize(0)
|
||||
{
|
||||
//
|
||||
// Setup pipes
|
||||
//
|
||||
SECURITY_ATTRIBUTES saAttr;
|
||||
|
||||
// Set the bInheritHandle flag so pipe handles are inherited.
|
||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
// Create a pipe for the child process's STDOUT.
|
||||
Enforce<PluginException>(CreatePipe(&m_ChildStd_OUT_Rd, &m_ChildStd_OUT_Wr, &saAttr, 0) == TRUE, string("Error creating STDOUT for '") + cmd + "' " + ErrorCodeToMsg(GetLastError()));
|
||||
|
||||
// Ensure the read handle to the pipe for STDOUT is not inherited.
|
||||
Enforce<PluginException>(SetHandleInformation(m_ChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) == TRUE, string("Error STDOUT no inherit '") + cmd + "' " + ErrorCodeToMsg(GetLastError()));
|
||||
|
||||
// Create a pipe for the child process's STDIN.
|
||||
Enforce<PluginException>(CreatePipe(&m_ChildStd_IN_Rd, &m_ChildStd_IN_Wr, &saAttr, 0) == TRUE, string("Error creating STDIN for '") + cmd + "' " + ErrorCodeToMsg(GetLastError()));
|
||||
|
||||
// Ensure the write handle to the pipe for STDIN is not inherited.
|
||||
Enforce<PluginException>(SetHandleInformation(m_ChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) == TRUE, string("Error STDIN no inherit '") + cmd + "'" + ErrorCodeToMsg(GetLastError()));
|
||||
|
||||
//
|
||||
// Create child process
|
||||
//
|
||||
STARTUPINFO siStartInfo;
|
||||
BOOL bSuccess = FALSE;
|
||||
|
||||
// Set up members of the PROCESS_INFORMATION structure.
|
||||
|
||||
ZeroMemory( &m_ProcInfo, sizeof(PROCESS_INFORMATION) );
|
||||
|
||||
// Set up members of the STARTUPINFO structure.
|
||||
// This structure specifies the STDIN and STDOUT handles for redirection.
|
||||
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
|
||||
siStartInfo.cb = sizeof(STARTUPINFO);
|
||||
siStartInfo.hStdError = m_ChildStd_OUT_Wr;
|
||||
siStartInfo.hStdOutput = m_ChildStd_OUT_Wr;
|
||||
siStartInfo.hStdInput = m_ChildStd_IN_Rd;
|
||||
siStartInfo.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
||||
siStartInfo.wShowWindow = SW_HIDE;
|
||||
|
||||
// Create the child process.
|
||||
bSuccess = CreateProcess(NULL,
|
||||
TEXT(const_cast<char *>(m_Command.c_str())), // command line
|
||||
NULL, // process security attributes
|
||||
NULL, // primary thread security attributes
|
||||
TRUE, // handles are inherited
|
||||
0, // creation flags
|
||||
NULL, // use parent's environment
|
||||
NULL, // use parent's current directory
|
||||
&siStartInfo, // STARTUPINFO pointer
|
||||
&m_ProcInfo); // receives PROCESS_INFORMATION
|
||||
|
||||
// If an error occurs, exit the application.
|
||||
Enforce<PluginException>(bSuccess == TRUE, string("Could not start '") + cmd + "'" + ErrorCodeToMsg(GetLastError()));
|
||||
|
||||
// Close the client pipe ends here or we will keep the handles open even though the
|
||||
// client has terminated. This is turn would block reads/writes and we would get EOL.
|
||||
CloseHandle(m_ChildStd_OUT_Wr);
|
||||
CloseHandle(m_ChildStd_IN_Rd);
|
||||
}
|
||||
|
||||
POpen::~POpen()
|
||||
{
|
||||
string msg = "";
|
||||
if (m_ChildStd_IN_Rd != NULL && !CloseHandle(m_ChildStd_IN_Rd))
|
||||
msg += ErrorCodeToMsg(GetLastError()) + " - ";
|
||||
if (m_ChildStd_IN_Wr != NULL && !CloseHandle(m_ChildStd_IN_Wr))
|
||||
msg += ErrorCodeToMsg(GetLastError()) + " - ";
|
||||
if (m_ChildStd_OUT_Rd != NULL && !CloseHandle(m_ChildStd_OUT_Rd))
|
||||
msg += ErrorCodeToMsg(GetLastError()) + " - ";
|
||||
if (m_ChildStd_OUT_Wr != NULL && !CloseHandle(m_ChildStd_OUT_Wr))
|
||||
msg += ErrorCodeToMsg(GetLastError()) + " - ";
|
||||
if (m_ProcInfo.hProcess != NULL && !CloseHandle(m_ProcInfo.hProcess))
|
||||
msg += ErrorCodeToMsg(GetLastError()) + " - ";
|
||||
if (m_ProcInfo.hThread != NULL && !CloseHandle(m_ProcInfo.hThread))
|
||||
msg += ErrorCodeToMsg(GetLastError()) + " - ";
|
||||
// msg could be printed or something at some point
|
||||
}
|
||||
|
||||
bool POpen::ReadLine(string& result)
|
||||
{
|
||||
static int aa = 0;
|
||||
|
||||
if (m_BufSize == BUFSIZE+1)
|
||||
return false;
|
||||
|
||||
DWORD dwRead;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
||||
DWORD i = 0;
|
||||
for ( ; i < m_BufSize; ++i)
|
||||
if (m_Buf[i] == '\n')
|
||||
break;
|
||||
|
||||
//if (aa++ == 23)
|
||||
// throw PluginException(string("got '") + string(m_Buf, m_BufSize) + "'" + ToString(m_BufSize));
|
||||
|
||||
// throw PluginException(ToString(m_BufSize) + " " + ToString(i) + ": " + string(m_Buf, dwRead));
|
||||
if (i != m_BufSize)
|
||||
{
|
||||
// Found a newline
|
||||
bool stripCR = i > 0 && m_Buf[i-1] == '\r';
|
||||
|
||||
result.assign(m_Buf, stripCR ? i-1 : i);
|
||||
|
||||
if (i+1 < m_BufSize)
|
||||
{
|
||||
// +1 to skip \n
|
||||
m_BufSize -= i + 1;
|
||||
memmove(m_Buf, m_Buf + i + 1, m_BufSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_BufSize = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Need more data
|
||||
DWORD bufferLeft = BUFSIZE - m_BufSize - 1;
|
||||
Enforce<PluginException>(bufferLeft > 0, string("Buffer overflow in ReadLine for '") + m_Command + "'");
|
||||
|
||||
if (!ReadFile( m_ChildStd_OUT_Rd, m_Buf + m_BufSize, bufferLeft, &dwRead, NULL))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
if (err != ERROR_BROKEN_PIPE)
|
||||
throw PluginException(string("Error during read from '") + m_Command + "': " + ErrorCodeToMsg(GetLastError()));
|
||||
dwRead = 0;
|
||||
}
|
||||
|
||||
if (dwRead == 0)
|
||||
{
|
||||
// End if pipe
|
||||
if (m_BufSize != 0)
|
||||
{
|
||||
result.assign(m_Buf, m_BufSize);
|
||||
m_BufSize = BUFSIZE+1; // signal no more data
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// look for newline
|
||||
m_BufSize += dwRead;
|
||||
}
|
||||
}
|
||||
|
||||
const size_t kDefaultPathBufferSize = 1024;
|
||||
|
||||
void POpen::ReadIntoFile(const std::string& path)
|
||||
{
|
||||
wchar_t widePath[kDefaultPathBufferSize];
|
||||
ConvertUnityPathName(path.c_str(), widePath, kDefaultPathBufferSize);
|
||||
HANDLE fh = CreateFileW(
|
||||
widePath,
|
||||
GENERIC_WRITE | GENERIC_READ,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
|
||||
Enforce<PluginException>(fh != INVALID_HANDLE_VALUE, string("Invalid result file handle for ReadIntoFile during '") + m_Command + "' " + ErrorCodeToMsg(GetLastError()));
|
||||
|
||||
DWORD dwRead, dwWritten;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
||||
|
||||
if (!ReadFile( m_ChildStd_OUT_Rd, m_Buf, BUFSIZE, &dwRead, NULL))
|
||||
{
|
||||
CloseHandle(fh);
|
||||
throw PluginException(string("Error during read from '") + m_Command + "': " + ErrorCodeToMsg(GetLastError()));
|
||||
}
|
||||
|
||||
if( dwRead == 0 ) break; // end of pipe
|
||||
|
||||
if (!WriteFile(fh, m_Buf, dwRead, &dwWritten, NULL))
|
||||
{
|
||||
CloseHandle(fh);
|
||||
throw PluginException(string("Error during read from '") + m_Command + "': " + ErrorCodeToMsg(GetLastError()));
|
||||
}
|
||||
}
|
||||
CloseHandle(fh);
|
||||
}
|
||||
|
||||
#else // posix
|
||||
|
||||
POpen::POpen(const string& cmd) : m_Command(cmd)
|
||||
{
|
||||
m_Handle = popen(cmd.c_str(), "r");
|
||||
Enforce<PluginException>(m_Handle, string("Error starting '") + cmd + "'");
|
||||
}
|
||||
|
||||
POpen::~POpen()
|
||||
{
|
||||
if (m_Handle)
|
||||
pclose(m_Handle);
|
||||
}
|
||||
|
||||
bool POpen::ReadLine(string& result)
|
||||
{
|
||||
Enforce<PluginException>(m_Handle, string("Null handle when reading from command pipe: ") + m_Command);
|
||||
|
||||
const size_t BUFSIZE = 8192;
|
||||
static char buf[BUFSIZE];
|
||||
if (feof(m_Handle)) return false;
|
||||
|
||||
char* res = fgets(buf, BUFSIZE, m_Handle);
|
||||
if (!res)
|
||||
{
|
||||
if (feof(m_Handle))
|
||||
return false; // no more data
|
||||
|
||||
throw PluginException(string("Error reading command pipe :") +
|
||||
strerror(ferror(m_Handle))
|
||||
+ " - " + m_Command);
|
||||
}
|
||||
result = res;
|
||||
string::reverse_iterator i = result.rbegin();
|
||||
if (!result.empty() && *i == '\n')
|
||||
result.resize(result.size()-1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void POpen::ReadIntoFile(const std::string& path)
|
||||
{
|
||||
Enforce<PluginException>(m_Handle, string("Null handle when reading into filefrom command pipe: ") + m_Command);
|
||||
|
||||
const size_t BUFSIZE = 8192;
|
||||
static char buf[BUFSIZE];
|
||||
|
||||
FILE* fh = fopen(path.c_str(), "w");
|
||||
|
||||
if (feof(m_Handle))
|
||||
{
|
||||
fclose(fh);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t bytes = fread(buf, 1, BUFSIZE, m_Handle);
|
||||
while (bytes == BUFSIZE)
|
||||
{
|
||||
if (fwrite(buf, 1, bytes, fh) != bytes)
|
||||
{
|
||||
// Error writing to disk
|
||||
fclose(fh);
|
||||
throw PluginException(string("Error writing process output into file: ") + path + " for command " + m_Command);
|
||||
}
|
||||
bytes = fread(buf, BUFSIZE, 1, m_Handle);
|
||||
}
|
||||
|
||||
if (feof(m_Handle))
|
||||
{
|
||||
if (bytes && fwrite(buf, 1, bytes, fh) != bytes)
|
||||
{
|
||||
// Error writing to disk
|
||||
fclose(fh);
|
||||
throw PluginException(string("Error writing process end output into file: ") + path);
|
||||
}
|
||||
fclose(fh);
|
||||
}
|
||||
else
|
||||
{
|
||||
stringstream os;
|
||||
os << "Error writing process output to file: ";
|
||||
os << path << " code " << ferror(fh);
|
||||
os << " for command " << m_Command << std::endl;
|
||||
fclose(fh);
|
||||
throw PluginException(os.str());
|
||||
}
|
||||
}
|
||||
|
||||
#endif // end defined(_WINDOWS) or posix
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
#if defined(_WINDOWS)
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
// Run a command line read result.
|
||||
// This is done blocking which is ok since Unity will timeout
|
||||
class POpen
|
||||
{
|
||||
public:
|
||||
POpen(const std::string& cmd);
|
||||
~POpen();
|
||||
bool ReadLine(std::string& result);
|
||||
void ReadIntoFile(const std::string& path);
|
||||
private:
|
||||
std::string m_Command;
|
||||
#if defined(_WINDOWS)
|
||||
HANDLE m_ChildStd_IN_Rd;
|
||||
HANDLE m_ChildStd_IN_Wr;
|
||||
HANDLE m_ChildStd_OUT_Rd;
|
||||
HANDLE m_ChildStd_OUT_Wr;
|
||||
PROCESS_INFORMATION m_ProcInfo;
|
||||
CHAR m_Buf[4096];
|
||||
DWORD m_BufSize;
|
||||
|
||||
#else // posix
|
||||
FILE* m_Handle;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef std::auto_ptr<POpen> APOpen;
|
|
@ -61,7 +61,7 @@ unityplugin::LogStream& UnityConnection::Log()
|
|||
|
||||
bool UnityConnection::IsConnected() const
|
||||
{
|
||||
return m_UnityPipe;
|
||||
return m_UnityPipe != NULL;
|
||||
}
|
||||
|
||||
UnityPipe& UnityConnection::Pipe()
|
||||
|
|
|
@ -142,100 +142,6 @@ bool IsReadOnly(const std::string& path)
|
|||
}
|
||||
*/
|
||||
|
||||
POpen::POpen(const std::string& cmd) : m_Command(cmd)
|
||||
{
|
||||
#if defined(_WINDOWS)
|
||||
m_Handle = _popen(cmd.c_str(), "r");
|
||||
#else
|
||||
m_Handle = popen(cmd.c_str(), "r");
|
||||
#endif
|
||||
Enforce<PluginException>(m_Handle, string("Error starting '") + cmd + "'");
|
||||
}
|
||||
|
||||
POpen::~POpen()
|
||||
{
|
||||
if (m_Handle)
|
||||
#if defined(_WINDOWS)
|
||||
_pclose(m_Handle);
|
||||
#else
|
||||
pclose(m_Handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool POpen::ReadLine(std::string& result)
|
||||
{
|
||||
Enforce<PluginException>(m_Handle, string("Null handle when reading from command pipe: ") + m_Command);
|
||||
|
||||
const size_t BUFSIZE = 8192;
|
||||
static char buf[BUFSIZE];
|
||||
if (feof(m_Handle)) return false;
|
||||
|
||||
char* res = fgets(buf, BUFSIZE, m_Handle);
|
||||
if (!res)
|
||||
{
|
||||
if (feof(m_Handle))
|
||||
return false; // no more data
|
||||
|
||||
throw PluginException(string("Error reading command pipe :") +
|
||||
strerror(ferror(m_Handle))
|
||||
+ " - " + m_Command);
|
||||
}
|
||||
result = res;
|
||||
string::reverse_iterator i = result.rbegin();
|
||||
if (!result.empty() && *i == '\n')
|
||||
result.resize(result.size()-1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void POpen::ReadIntoFile(const std::string& path)
|
||||
{
|
||||
Enforce<PluginException>(m_Handle, string("Null handle when reading into filefrom command pipe: ") + m_Command);
|
||||
|
||||
const size_t BUFSIZE = 8192;
|
||||
static char buf[BUFSIZE];
|
||||
|
||||
FILE* fh = fopen(path.c_str(), "w");
|
||||
|
||||
if (feof(m_Handle))
|
||||
{
|
||||
fclose(fh);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t bytes = fread(buf, 1, BUFSIZE, m_Handle);
|
||||
while (bytes == BUFSIZE)
|
||||
{
|
||||
if (fwrite(buf, 1, bytes, fh) != bytes)
|
||||
{
|
||||
// Error writing to disk
|
||||
fclose(fh);
|
||||
throw PluginException(string("Error writing process output into file: ") + path + " for command " + m_Command);
|
||||
}
|
||||
bytes = fread(buf, BUFSIZE, 1, m_Handle);
|
||||
}
|
||||
|
||||
if (feof(m_Handle))
|
||||
{
|
||||
if (bytes && fwrite(buf, 1, bytes, fh) != bytes)
|
||||
{
|
||||
// Error writing to disk
|
||||
fclose(fh);
|
||||
throw PluginException(string("Error writing process end output into file: ") + path);
|
||||
}
|
||||
fclose(fh);
|
||||
}
|
||||
else
|
||||
{
|
||||
stringstream os;
|
||||
os << "Error writing process output to file: ";
|
||||
os << path << " code " << ferror(fh);
|
||||
os << " for command " << m_Command << std::endl;
|
||||
fclose(fh);
|
||||
throw PluginException(os.str());
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
#include <stdio.h>
|
||||
string ErrorCodeToMsg( DWORD code )
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <vector>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include "POpen.h"
|
||||
|
||||
std::string IntToString (int i);
|
||||
size_t Tokenize(std::vector<std::string>& result, const std::string& str,
|
||||
|
@ -50,24 +51,7 @@ std::string ToString(const T& v1, const T& v2, const T& v3)
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
// Run a command line read result.
|
||||
// This is done blocking which is ok since Unity will timeout
|
||||
class POpen
|
||||
{
|
||||
public:
|
||||
POpen(const std::string& cmd);
|
||||
~POpen();
|
||||
bool ReadLine(std::string& result);
|
||||
void ReadIntoFile(const std::string& path);
|
||||
private:
|
||||
std::string m_Command;
|
||||
FILE* m_Handle;
|
||||
};
|
||||
|
||||
typedef std::auto_ptr<POpen> APOpen;
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
#include <Windows.h>
|
||||
std::string ErrorCodeToMsg( DWORD code );
|
||||
#endif
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<ClCompile Include="..\Common\CommandLine.cpp" />
|
||||
<ClCompile Include="..\Common\FileSystem.cpp" />
|
||||
<ClCompile Include="..\Common\Log.cpp" />
|
||||
<ClCompile Include="..\Common\POpen.cpp" />
|
||||
<ClCompile Include="..\Common\Status.cpp" />
|
||||
<ClCompile Include="..\Common\Task.cpp" />
|
||||
<ClCompile Include="..\Common\UnityConnection.cpp" />
|
||||
|
@ -72,6 +73,7 @@
|
|||
<ClInclude Include="..\Common\Dispatch.h" />
|
||||
<ClInclude Include="..\Common\FileSystem.h" />
|
||||
<ClInclude Include="..\Common\Log.h" />
|
||||
<ClInclude Include="..\Common\POpen.h" />
|
||||
<ClInclude Include="..\Common\Status.h" />
|
||||
<ClInclude Include="..\Common\Task.h" />
|
||||
<ClInclude Include="..\Common\UnityConnection.h" />
|
||||
|
|
|
@ -140,6 +140,9 @@
|
|||
<ClCompile Include="..\Common\UnityConnection.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Common\POpen.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Common\Changes.h">
|
||||
|
@ -232,5 +235,8 @@
|
|||
<ClInclude Include="..\Common\Commands\Submit.h">
|
||||
<Filter>Common\Commands</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Common\POpen.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -46,7 +46,7 @@ public:
|
|||
Pipe().Log() << "Ensure editable source " << paths << unityplugin::Endl;
|
||||
|
||||
string err;
|
||||
bool editable = src.GetState() & (kCheckedOutLocal | kAddedLocal | kLockedLocal);
|
||||
bool editable = (src.GetState() & (kCheckedOutLocal | kAddedLocal | kLockedLocal)) != 0;
|
||||
|
||||
if (!editable)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@ public:
|
|||
resp.addTrait("svnPassword", "Password", "Subversion password", "", ConfigResponse::TF_Required | ConfigResponse::TF_Password);
|
||||
resp.addTrait("svnRepos", "Repository", "Subversion Repository", "", ConfigResponse::TF_Required);
|
||||
resp.addTrait("svnOptions", "Options", "Subversion extra options", "", ConfigResponse::TF_None);
|
||||
resp.addTrait("svnExecutable", "Executable", "Path to the svn.exe executable", task.GetSvnExecutable(), ConfigResponse::TF_None);
|
||||
}
|
||||
else if (req.key == "pluginVersions")
|
||||
{
|
||||
|
@ -46,6 +47,11 @@ public:
|
|||
req.conn.Log() << "Set options to " << req.values[0] << unityplugin::Endl;
|
||||
task.SetOptions(Join(req.values, " "));
|
||||
}
|
||||
else if (req.key == "svnExcutable")
|
||||
{
|
||||
req.conn.Log() << "Set executable path to " << req.values[0] << unityplugin::Endl;
|
||||
task.SetSvnExecutable(Join(req.values, " "));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string msg = "Unknown config field set on subversion plugin: ";
|
||||
|
|
|
@ -10,6 +10,7 @@ using namespace std;
|
|||
|
||||
SvnTask::SvnTask() : m_Task(NULL)
|
||||
{
|
||||
SetSvnExecutable(""); // Set default svn executable
|
||||
}
|
||||
|
||||
SvnTask::~SvnTask()
|
||||
|
@ -57,6 +58,32 @@ const std::string& SvnTask::GetOptions() const
|
|||
return m_OptionsConfig;
|
||||
}
|
||||
|
||||
void SvnTask::SetSvnExecutable(const std::string& e)
|
||||
{
|
||||
if (!e.empty())
|
||||
{
|
||||
if (PathExists(e))
|
||||
m_SvnPath = e;
|
||||
else
|
||||
m_SvnPath.clear();
|
||||
}
|
||||
|
||||
if (e.empty())
|
||||
{
|
||||
#if defined(_WINDOWS)
|
||||
m_SvnPath = PluginPath();
|
||||
m_SvnPath = m_SvnPath.substr(0, m_SvnPath.rfind('\\', m_SvnPath.rfind('\\') - 1)) + "\\svn\\svn.exe";
|
||||
#else // posix
|
||||
m_SvnPath = "/usr/bin/svn";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& SvnTask::GetSvnExecutable() const
|
||||
{
|
||||
return m_SvnPath;
|
||||
}
|
||||
|
||||
std::string SvnTask::GetCredentials() const
|
||||
{
|
||||
string c;
|
||||
|
@ -91,7 +118,6 @@ int SvnTask::Run()
|
|||
|
||||
UnityCommand cmd;
|
||||
CommandArgs args;
|
||||
m_SvnPath = "/usr/bin/svn";
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -311,7 +337,6 @@ void SvnTask::GetStatusWithChangelists(const VersionedAssetList& assets,
|
|||
// status for different areas. Following at are space separated
|
||||
// fields in order: working revision, last commited revision, last commited author
|
||||
// The last field is the file path and can include spaces
|
||||
|
||||
if (StartsWith(line, "--- Changelist"))
|
||||
{
|
||||
const int prefixLen = 15; // "-- Changelist '" length
|
||||
|
@ -398,14 +423,14 @@ void SvnTask::GetLog(SvnLogResult& result, const std::string& from, const std::s
|
|||
|
||||
while (ppipe->ReadLine(line))
|
||||
{
|
||||
Enforce<SvnException>(StartsWith(line, "--------------"), "Invalid log header top");
|
||||
Enforce<SvnException>(StartsWith(line, "--------------"), string("Invalid log header top: ") + line);
|
||||
|
||||
// Skip first line of "------"
|
||||
if (!ppipe->ReadLine(line))
|
||||
break;
|
||||
|
||||
|
||||
Enforce<SvnException>(line.length() >= MIN_HEADER_LINE_LENGTH && line[0] == 'r',
|
||||
"Invalid log header");
|
||||
string("Invalid log header: ") + line);
|
||||
|
||||
toks.clear();
|
||||
size_t size = Tokenize(toks, line, "|");
|
||||
|
|
|
@ -20,6 +20,8 @@ public:
|
|||
const std::string& GetPassword() const;
|
||||
void SetOptions(const std::string& p);
|
||||
const std::string& GetOptions() const;
|
||||
void SetSvnExecutable(const std::string& e);
|
||||
const std::string& GetSvnExecutable() const;
|
||||
|
||||
void SetAssetsPath(const std::string& p);
|
||||
const std::string& GetAssetsPath() const;
|
||||
|
|
|
@ -92,6 +92,7 @@ _SCL_SECURE_NO_DEPRECATE
|
|||
<ClCompile Include="..\Common\CommandLine.cpp" />
|
||||
<ClCompile Include="..\Common\FileSystem.cpp" />
|
||||
<ClCompile Include="..\Common\Log.cpp" />
|
||||
<ClCompile Include="..\Common\POpen.cpp" />
|
||||
<ClCompile Include="..\Common\Status.cpp" />
|
||||
<ClCompile Include="..\Common\Task.cpp" />
|
||||
<ClCompile Include="..\Common\UnityConnection.cpp" />
|
||||
|
@ -120,6 +121,7 @@ _SCL_SECURE_NO_DEPRECATE
|
|||
<ClInclude Include="..\Common\Dispatch.h" />
|
||||
<ClInclude Include="..\Common\FileSystem.h" />
|
||||
<ClInclude Include="..\Common\Log.h" />
|
||||
<ClInclude Include="..\Common\POpen.h" />
|
||||
<ClInclude Include="..\Common\Status.h" />
|
||||
<ClInclude Include="..\Common\Task.h" />
|
||||
<ClInclude Include="..\Common\UnityConnection.h" />
|
||||
|
|
|
@ -51,6 +51,9 @@
|
|||
<ClCompile Include="Source\SvnTask.cpp">
|
||||
<Filter>SvnPlugin</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Common\POpen.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Common\Changes.h">
|
||||
|
@ -188,5 +191,8 @@
|
|||
<ClInclude Include="Source\SvnUnlockCommand.h">
|
||||
<Filter>SvnPlugin</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Common\POpen.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
Загрузка…
Ссылка в новой задаче