• R/O
  • SSH
  • HTTPS

backup-svn: Commit


Commit MetaInfo

Revision7 (tree)
Time2020-01-17 06:08:02
Authorgottfried

Log Message

Added functionality to read output from svnadmin

Change Summary

Incremental Difference

--- trunk/backup-svn/BackupSVN.cpp (nonexistent)
+++ trunk/backup-svn/BackupSVN.cpp (revision 7)
@@ -0,0 +1,183 @@
1+
2+#include "BackupSVN.h"
3+#include "IniFile.h"
4+#include "StringTools.h"
5+#include <iostream>
6+
7+#define WIN32_LEAN_AND_MEAN
8+#define NOMINMAX
9+#include <Windows.h>
10+
11+using namespace std;
12+
13+
14+cBackupSVN::cBackupSVN(const wchar_t *svnadminpath, const wchar_t *repopath) :
15+ mSvnAdminPath(svnadminpath),
16+ mSvnRepoPath(repopath)
17+{
18+}
19+
20+
21+cBackupSVN::~cBackupSVN()
22+{
23+}
24+
25+int cBackupSVN::run()
26+{
27+ // first read all subdirs
28+ scanRepos();
29+
30+ // then check repository and dump if changed:
31+ int result = checkRepos();
32+
33+ //if all ok, then return 0
34+ return result;
35+}
36+
37+
38+void cBackupSVN::scanRepos()
39+{
40+ mRepolist.clear();
41+
42+ std::wstring pattern(L"*");
43+ WIN32_FIND_DATAW data;
44+ HANDLE hFind;
45+
46+ hFind = FindFirstFileW(pattern.c_str(), &data);
47+ if(hFind != INVALID_HANDLE_VALUE)
48+ {
49+ do
50+ {
51+ if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
52+ {
53+ std::wstring filename = data.cFileName;
54+ if(filename != L"." && filename != L"..")
55+ {
56+ mRepolist.push_back(filename);
57+ }
58+ }
59+ } while(FindNextFileW(hFind, &data) != 0);
60+
61+ FindClose(hFind);
62+ }
63+}
64+
65+int cBackupSVN::checkRepos()
66+{
67+ wstring svnadmin = mSvnAdminPath.c_str();
68+ if(svnadmin.length())
69+ svnadmin += L'/';
70+ svnadmin += L"svnadmin";
71+
72+ // check repository with:
73+ /*
74+ > "svnadmin.exe" info <repopath>
75+ Path: <repopath>
76+ UUID: ########-####-####-####-############
77+ Revisions: 0001
78+ Repository Format: 5
79+ Compatible With Version: 1.10.0
80+ Repository Capability: mergeinfo
81+ Filesystem Type: fsfs
82+ Filesystem Format: 8
83+ FSFS Sharded: yes
84+ FSFS Shard Size: 1000
85+ FSFS Shards Packed: 0/1
86+ FSFS Logical Addressing: yes
87+ Configuration File: <repopath>\db\fsfs.conf
88+ */
89+
90+ int result = 0;
91+ for(vector<wstring>::const_iterator it = mRepolist.cbegin(); it != mRepolist.cend(); ++it)
92+ {
93+ const wstring &repo = *it;
94+
95+ wstring svnadmininfo = L"\"" + svnadmin + L"\"";
96+ svnadmininfo += L" info ";
97+ svnadmininfo += L"\"" + repo + L"\"";
98+
99+ string strResult = execCmd(svnadmininfo.c_str());
100+
101+
102+ cout << strResult << endl;
103+
104+ // TODO: if version changed:
105+ //dumpRepos(svnadmin.c_str(), repo.c_str());
106+ }
107+
108+ return result;
109+}
110+
111+void cBackupSVN::dumpRepos(const wchar_t *svnadmin, const wchar_t *repo)
112+{
113+}
114+
115+
116+
117+string cBackupSVN::execCmd(const wchar_t *cmd)
118+{
119+ string strResult;
120+ HANDLE hPipeRead, hPipeWrite;
121+
122+ SECURITY_ATTRIBUTES saAttr ={sizeof(SECURITY_ATTRIBUTES)};
123+ saAttr.bInheritHandle = TRUE; // Pipe handles are inherited by child process.
124+ saAttr.lpSecurityDescriptor = NULL;
125+
126+ // Create a pipe to get results from child's stdout.
127+ if(!CreatePipe(&hPipeRead, &hPipeWrite, &saAttr, 0))
128+ return strResult;
129+
130+ STARTUPINFOW si ={sizeof(STARTUPINFOW)};
131+ si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
132+ si.hStdOutput = hPipeWrite;
133+ si.hStdError = hPipeWrite;
134+ si.wShowWindow = SW_HIDE; // Prevents cmd window from flashing.
135+ // Requires STARTF_USESHOWWINDOW in dwFlags.
136+
137+ PROCESS_INFORMATION pi ={0};
138+
139+ BOOL fSuccess = CreateProcessW(NULL, (LPWSTR)cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
140+ if(! fSuccess)
141+ {
142+ CloseHandle(hPipeWrite);
143+ CloseHandle(hPipeRead);
144+ return strResult;
145+ }
146+
147+ bool bProcessEnded = false;
148+ for(; !bProcessEnded;)
149+ {
150+ // Give some timeslice (50 ms), so we won't waste 100% CPU.
151+ bProcessEnded = WaitForSingleObject(pi.hProcess, 50) == WAIT_OBJECT_0;
152+
153+ // Even if process exited - we continue reading, if
154+ // there is some data available over pipe.
155+ for(;;)
156+ {
157+ char buf[1024];
158+ DWORD dwRead = 0;
159+ DWORD dwAvail = 0;
160+
161+ if(!::PeekNamedPipe(hPipeRead, NULL, 0, NULL, &dwAvail, NULL))
162+ break;
163+
164+ if(!dwAvail) // No data available, return
165+ break;
166+
167+ DWORD readlength = sizeof(buf) - 1;
168+ if(readlength > dwAvail)
169+ readlength = dwAvail;
170+ if(!::ReadFile(hPipeRead, buf, readlength, &dwRead, NULL) || !dwRead)
171+ break; // Error, the child process might ended
172+
173+ buf[dwRead] = 0;
174+ strResult += buf;
175+ }
176+ } //for
177+
178+ CloseHandle(hPipeWrite);
179+ CloseHandle(hPipeRead);
180+ CloseHandle(pi.hProcess);
181+ CloseHandle(pi.hThread);
182+ return strResult;
183+}
--- trunk/backup-svn/BackupSVN.h (nonexistent)
+++ trunk/backup-svn/BackupSVN.h (revision 7)
@@ -0,0 +1,25 @@
1+#pragma once
2+
3+#include <string>
4+#include <vector>
5+
6+class cBackupSVN
7+{
8+public:
9+ cBackupSVN(const wchar_t *svnadminpath, const wchar_t *repopath);
10+ ~cBackupSVN();
11+
12+ int run();
13+
14+private:
15+ std::wstring mSvnAdminPath;
16+ std::wstring mSvnRepoPath;
17+ std::vector<std::wstring> mRepolist;
18+
19+ void scanRepos();
20+ int checkRepos();
21+ void dumpRepos(const wchar_t *svnadmin, const wchar_t *repo);
22+
23+ std::string execCmd(const wchar_t *cmd);
24+};
25+
--- trunk/backup-svn/IniFile.cpp (revision 6)
+++ trunk/backup-svn/IniFile.cpp (revision 7)
@@ -1,5 +1,6 @@
11
22 #include "IniFile.h"
3+#include "StringTools.h"
34 #include <cstdio>
45
56 #define WIN32_LEAN_AND_MEAN
@@ -26,25 +27,18 @@
2627 // check if file exists
2728 #pragma warning( push )
2829 #pragma warning (disable : 4996) //error C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
29- FILE *fp = fopen(filename, "r");
30- if(fp)
31- {
32- fclose(fp);
30+ FILE *fp = fopen(filename, "r");
31+ if(fp)
32+ {
33+ fclose(fp);
3334 #pragma warning( pop )
3435
3536 mFile = filename;
3637
3738 // Converts the path to wide characters
38- size_t len = mFile.length();
39- wchar_t *wfilename = new wchar_t[len+1];
40- MultiByteToWideChar(0, 0, mFile.c_str(), len + 1, wfilename, len + 1);
41- mwFile = wfilename;
42- delete[] wfilename;
43-
44- //GetPrivateProfileInt();
45-
39+ mwFile = cStringTools::convertToWString(mFile.c_str());
4640 return true;
47- }
41+ }
4842
4943 return false;
5044 }
--- trunk/backup-svn/StringTools.cpp (nonexistent)
+++ trunk/backup-svn/StringTools.cpp (revision 7)
@@ -0,0 +1,46 @@
1+#include "StringTools.h"
2+
3+#include <cassert>
4+
5+#define WIN32_LEAN_AND_MEAN
6+#define NOMINMAX
7+#include <Windows.h>
8+
9+using namespace std;
10+
11+
12+cStringTools::cStringTools()
13+{
14+}
15+
16+
17+cStringTools::~cStringTools()
18+{
19+}
20+
21+
22+std::wstring cStringTools::convertToWString(const char *str)
23+{
24+ // Converts to wide characters
25+ size_t len = strlen(str) + 1;
26+
27+ wchar_t *converted = new wchar_t[len];
28+ MultiByteToWideChar(0, 0, str, len, converted, len);
29+ wstring retval = converted;
30+ delete[] converted;
31+
32+ return retval;
33+}
34+
35+std::string cStringTools::convertToString(const wchar_t *wstr)
36+{
37+ size_t len = wcslen(wstr) * 4 + 1;
38+
39+ char *converted = new char[len];
40+ char DefChar = ' ';
41+ WideCharToMultiByte(CP_ACP, 0, wstr, len, converted, len, &DefChar, NULL);
42+ string retval = converted;
43+ delete[] converted;
44+
45+ return retval;
46+}
--- trunk/backup-svn/StringTools.h (nonexistent)
+++ trunk/backup-svn/StringTools.h (revision 7)
@@ -0,0 +1,15 @@
1+#pragma once
2+
3+#include <string>
4+
5+
6+class cStringTools
7+{
8+public:
9+ cStringTools();
10+ ~cStringTools();
11+
12+ static std::wstring convertToWString(const char *str);
13+ static std::string convertToString(const wchar_t *wstr);
14+};
15+
--- trunk/backup-svn/backup-svn.ini (revision 6)
+++ trunk/backup-svn/backup-svn.ini (revision 7)
@@ -4,5 +4,9 @@
44
55 [FILES]
66 # Path where svnadmin found
7+# if no SVNADMIN_PATH is set, the svnadmin is get from default %PATH%
8+# use one of the following.
9+#SVNADMIN_PATH=C:\cygwin64\bin
10+#SVNADMIN_PATH=C:\cygwin\bin
11+#SVNADMIN_PATH=C:\Program Files (x86)\VisualSVN Server\bin
712 SVNADMIN_PATH=C:\Program Files\TortoiseSVN\bin
8-#SVNADMIN_PATH=C:\Program Files (x86)\VisualSVN Server\bin
--- trunk/backup-svn/main.cpp (revision 6)
+++ trunk/backup-svn/main.cpp (revision 7)
@@ -2,54 +2,59 @@
22 #include "stdafx.h"
33
44 #include "IniFile.h"
5+#include "BackupSVN.h"
6+#include "StringTools.h"
57 #include <direct.h> // _getcwd
8+#include <iostream>
69
10+using namespace std;
711
12+
813 int main(int argc, char *argv[])
914 {
1015 std::string app_path;
16+ std::string curr_path;
1117 std::string ini_file;
1218
13- // check if we run program from full path
14- std::string filepath = argv[0];
15- size_t pos = filepath.find_last_of("/\\");
16- if(pos != std::string::npos)
19+ // Get the current working directory:
1720 {
18- app_path = std::string(filepath.c_str(), pos);
19- ini_file = app_path + "/" + "backup-svn.ini";
20- if(!IniFile::Init(ini_file.c_str()))
21- pos = std::string::npos;
22- }
23- if(pos == std::string::npos)
24- {
25- // Get the current working directory:
2621 char *buffer = _getcwd(NULL, 0);
27-
2822 if(!buffer)
2923 perror("_getcwd error");
3024 else
3125 {
32- app_path = buffer;
26+ curr_path = buffer;
3327 free(buffer);
3428 }
3529 }
36-
30+
31+ // check if we run program from full path
32+ std::string filepath = argv[0];
33+ size_t pos = filepath.find_last_of("/\\");
34+ if(pos != std::string::npos)
35+ app_path = std::string(filepath.c_str(), pos);
36+ else
37+ app_path = curr_path;
38+
39+
3740 ini_file = app_path + "/" + "backup-svn.ini";
3841 if(!IniFile::Init(ini_file.c_str()))
3942 {
43+ ini_file = curr_path + "/" + "backup-svn.ini";
44+ if(!IniFile::Init(ini_file.c_str()))
45+ cerr << "No INI file found!" << endl;
4046 }
4147
48+ // Converts the path to wide characters
49+ wstring wcurr_path = cStringTools::convertToWString(curr_path.c_str());
50+
4251 //Get path for svnadmin
4352 std::wstring program_wpath = IniFile::getString(L"FILES", L"SVNADMIN_PATH", L"");
4453 //std::string program_path = IniFile::getString( "FILES", "SVNADMIN_PATH", "");
4554
46- std::wstring svnadmin = program_wpath;
47- if(svnadmin.length())
48- svnadmin += L'/';
49- svnadmin += L"svnadmin";
55+ cBackupSVN backup(program_wpath.c_str(), wcurr_path.c_str());
56+ int result = backup.run();
5057
51- //TODO: svnadmin dump "repodir" > "repodir.dump"
52-
53- return 0;
58+ return result;
5459 }
5560
Show on old repository browser