From 35f4130f3bb6981475deec3c8d1c869ea8920a42 Mon Sep 17 00:00:00 2001 From: cxl Date: Tue, 19 Aug 2008 13:30:02 +0000 Subject: [PATCH] Added usvn ability to detect folder replacement and to deal with the situation... git-svn-id: svn://ultimatepp.org/upp/trunk@357 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/usvn/SvnSync.cpp | 475 ++++++++++++++++++++++------------------ uppsrc/usvn/usvn.h | 249 ++++++++++----------- 2 files changed, 382 insertions(+), 342 deletions(-) diff --git a/uppsrc/usvn/SvnSync.cpp b/uppsrc/usvn/SvnSync.cpp index 3855d8b41..abcf5f309 100644 --- a/uppsrc/usvn/SvnSync.cpp +++ b/uppsrc/usvn/SvnSync.cpp @@ -1,218 +1,257 @@ -#include "usvn.h" - -SvnSync::SvnSync() -{ - CtrlLayoutOKCancel(*this, "SvnSynchronize SVN repositories"); - list.AddIndex(); - list.AddIndex(); - list.AddColumn("Action"); - list.AddColumn("Path"); - list.ColumnWidths("153 619"); - list.NoCursor().EvenRowColor(); - usr.NullText("use cached"); - pwd.NullText("use cached"); - Sizeable().Zoomable(); - setup <<= THISBACK(Setup); -} - -void SvnSync::Setup() -{ - works.Execute(); - SyncList(); -} - -int CharFilterSvnMsg(int c) -{ - return c >= 32 && c < 128 && c != '\"' ? c : 0; -} - -void SvnSync::SyncList() -{ - list.Clear(); - for(int i = 0; i < works.GetCount(); i++) { - SvnWork w = works[i]; - String path = GetFullPath(w.working); - list.Add(REPOSITORY, path, - AttrText("Working directory").SetFont(StdFont().Bold()).Ink(White).Paper(Blue), - AttrText(path).SetFont(Arial(20).Bold()).Paper(Blue).Ink(White)); - list.SetLineCy(list.GetCount() - 1, 26); - Vector ln = Split(Sys("svn status " + path), CharFilterCrLf); - bool actions = false; - for(int pass = 0; pass < 2; pass++) - for(int i = 0; i < ln.GetCount(); i++) { - String h = ln[i]; - if(h.GetCount() > 7) { - String file = h.Mid(7); - if(IsFullPath(file)) { - actions = true; - h.Trim(7); - bool simple = h.Mid(1, 6) == " "; - int action = simple ? String("MC?!").Find(h[0]) : -1; - String an; - Color color; - if(action < 0) { - color = Black; - if(simple && h[0] == 'A') - an = "svn add"; - else - if(simple && h[0] == 'D') - an = "svn delete"; - else { - an = h.Mid(0, 7); - color = Gray; - } - } - else { - static const char *as[] = { "Modify", "Conflict resolved", "Add", "Remove" }; - static Color c[] = { LtBlue, Magenta, Green, LtRed }; - an = as[action]; - color = c[action]; - } - if(pass == action < 0) { - int ii = list.GetCount(); - list.Add(action, file, - action <= 0 ? Value(AttrText(an).Ink(color)) : Value(true), - AttrText(" " + file.Mid(path.GetCount() + 1)).Ink(color)); - if(action > 0) - list.SetCtrl(ii, 0, confirm.Add().SetLabel(an).NoWantFocus()); - } - } - } - } - if(actions) { - list.Add(MESSAGE, Null, AttrText("Commit message:").SetFont(StdFont().Bold())); - list.SetLineCy(list.GetCount() - 1, EditField::GetStdHeight() + 4); - list.SetCtrl(list.GetCount() - 1, 1, message.Add().SetFilter(CharFilterSvnMsg)); - } - else - list.Add(-1, Null, "", AttrText("Nothing to do").SetFont(StdFont().Italic())); - } -} - -#ifdef PLATFORM_WIN32 -void sDeleteFolderDeep(const char *dir) -{ - { - FindFile ff(AppendFileName(dir, "*.*")); - while(ff) { - String name = ff.GetName(); - String p = AppendFileName(dir, name); - if(ff.IsFile()) { - SetFileAttributes(p, GetFileAttributes(p) & ~FILE_ATTRIBUTE_READONLY); - FileDelete(p); - } - else - if(ff.IsFolder()) - sDeleteFolderDeep(p); - ff.Next(); - } - } - DirectoryDelete(dir); -} -#else -void sDeleteFolderDeep(const char *path) -{ - DeleteFolderDeep(path); -} -#endif - -void SvnDel(const char *path) -{ - FindFile ff(AppendFileName(path, "*.*")); - while(ff) { - if(ff.IsFolder()) { - String dir = AppendFileName(path, ff.GetName()); - if(ff.GetName() == ".svn") - sDeleteFolderDeep(dir); - else - SvnDel(dir); - } - ff.Next(); - } -} - -void SvnSync::Dir(const char *dir) -{ - setup.Hide(); - works.Add(dir, Null, Null); -} - -void SvnSync::Perform() -{ - const Vector& cl = CommandLine(); - if(cl.GetCount()) { - for(int i = 0; i < cl.GetCount(); i++) { - String d = GetFullPath(cl[i]); - if(!DirectoryExists(cl[i])) { - Cerr() << cl[i] << " not a directory\n"; - SetExitCode(1); - return; - } - works.Add(d, ~usr, ~pwd); - } - setup.Hide(); - DoSync(); - } - else { - usr_lbl.Hide(); - usr.Hide(); - pwd_lbl.Hide(); - pwd.Hide(); - works.Load(LoadFile(ConfigFile("svnworks"))); - DoSync(); - SaveFile(ConfigFile("svnworks"), works.Save()); - } -} - -void SvnSync::DoSync() -{ - SyncList(); - if(Execute() != IDOK || list.GetCount() == 0) - return; - SysConsole sys; - int repoi = 0; - int i = 0; - while(i < list.GetCount()) { - SvnWork w = works[repoi++]; - i++; - String message; - while(i < list.GetCount()) { - int action = list.Get(i, 0); - String path = list.Get(i, 1); - if(action == MESSAGE) { - sys.System(SvnCmd("commit", w).Cat() << w.working << " -m \"" << list.Get(i, 3) << "\""); - i++; - break; - } - if(action == REPOSITORY) - break; - switch(action) { - case ADD: - SvnDel(path); - sys.System("svn add " + path); - break; - case REMOVE: - sys.System("svn delete " + path); - break; - case CONFLICT: - sys.System("svn resolved " + path); - break; - } - i++; - } - sys.System(SvnCmd("update", w).Cat() << w.working); - } - sys.Perform(); -} - -#ifdef flagMAIN -GUI_APP_MAIN -{ -// SvnSel svn; -// svn.Select(); -// svn.Select("svn://10.0.0.19/upp", "", ""); -// return; - - SvnSync().Perform(); -} -#endif +#include "usvn.h" + +SvnSync::SvnSync() +{ + CtrlLayoutOKCancel(*this, "SvnSynchronize SVN repositories"); + list.AddIndex(); + list.AddIndex(); + list.AddColumn("Action"); + list.AddColumn("Path"); + list.ColumnWidths("153 619"); + list.NoCursor().EvenRowColor(); + usr.NullText("use cached"); + pwd.NullText("use cached"); + Sizeable().Zoomable(); + setup <<= THISBACK(Setup); +} + +void SvnSync::Setup() +{ + works.Execute(); + SyncList(); +} + +int CharFilterSvnMsg(int c) +{ + return c >= 32 && c < 128 && c != '\"' ? c : 0; +} + +void SvnSync::SyncList() +{ + list.Clear(); + for(int i = 0; i < works.GetCount(); i++) { + SvnWork w = works[i]; + String path = GetFullPath(w.working); + list.Add(REPOSITORY, path, + AttrText("Working directory").SetFont(StdFont().Bold()).Ink(White).Paper(Blue), + AttrText(path).SetFont(Arial(20).Bold()).Paper(Blue).Ink(White)); + list.SetLineCy(list.GetCount() - 1, 26); + Vector ln = Split(Sys("svn status " + path), CharFilterCrLf); + bool actions = false; + for(int pass = 0; pass < 2; pass++) + for(int i = 0; i < ln.GetCount(); i++) { + String h = ln[i]; + if(h.GetCount() > 7) { + String file = h.Mid(7); + if(IsFullPath(file)) { + actions = true; + h.Trim(7); + bool simple = h.Mid(1, 6) == " "; + int action = simple ? String("MC?!~").Find(h[0]) : -1; + String an; + Color color; + if(action < 0) { + color = Black; + if(simple && h[0] == 'A') + an = "svn add"; + else + if(simple && h[0] == 'D') + an = "svn delete"; + else { + an = h.Mid(0, 7); + color = Gray; + } + } + else { + static const char *as[] = { "Modify", "Conflict resolved", "Add", "Remove", "Replace" }; + static Color c[] = { LtBlue, Magenta, Green, LtRed, LtMagenta }; + an = as[action]; + color = c[action]; + } + if(pass == action < 0) { + int ii = list.GetCount(); + list.Add(action, file, + action <= 0 ? Value(AttrText(an).Ink(color)) : Value(true), + AttrText(" " + file.Mid(path.GetCount() + 1)).Ink(color)); + if(action > 0) + list.SetCtrl(ii, 0, confirm.Add().SetLabel(an).NoWantFocus()); + } + } + } + } + if(actions) { + list.Add(MESSAGE, Null, AttrText("Commit message:").SetFont(StdFont().Bold())); + list.SetLineCy(list.GetCount() - 1, EditField::GetStdHeight() + 4); + list.SetCtrl(list.GetCount() - 1, 1, message.Add().SetFilter(CharFilterSvnMsg)); + } + else + list.Add(-1, Null, "", AttrText("Nothing to do").SetFont(StdFont().Italic())); + } +} + +#ifdef PLATFORM_WIN32 +void sDeleteFolderDeep(const char *dir) +{ + { + FindFile ff(AppendFileName(dir, "*.*")); + while(ff) { + String name = ff.GetName(); + String p = AppendFileName(dir, name); + if(ff.IsFile()) { + SetFileAttributes(p, GetFileAttributes(p) & ~FILE_ATTRIBUTE_READONLY); + FileDelete(p); + } + else + if(ff.IsFolder()) + sDeleteFolderDeep(p); + ff.Next(); + } + } + DirectoryDelete(dir); +} +#else +void sDeleteFolderDeep(const char *path) +{ + DeleteFolderDeep(path); +} +#endif + +void SvnDel(const char *path) +{ + FindFile ff(AppendFileName(path, "*.*")); + while(ff) { + if(ff.IsFolder()) { + String dir = AppendFileName(path, ff.GetName()); + if(ff.GetName() == ".svn") + sDeleteFolderDeep(dir); + else + SvnDel(dir); + } + ff.Next(); + } +} + +void SvnSync::Dir(const char *dir) +{ + setup.Hide(); + works.Add(dir, Null, Null); +} + +void SvnSync::Perform() +{ + const Vector& cl = CommandLine(); + if(cl.GetCount()) { + for(int i = 0; i < cl.GetCount(); i++) { + String d = GetFullPath(cl[i]); + if(!DirectoryExists(cl[i])) { + Cerr() << cl[i] << " not a directory\n"; + SetExitCode(1); + return; + } + works.Add(d, ~usr, ~pwd); + } + setup.Hide(); + DoSync(); + } + else { + usr_lbl.Hide(); + usr.Hide(); + pwd_lbl.Hide(); + pwd.Hide(); + works.Load(LoadFile(ConfigFile("svnworks"))); + DoSync(); + SaveFile(ConfigFile("svnworks"), works.Save()); + } +} + +void MoveSvn(const String& path, const String& tp) +{ + FindFile ff(AppendFileName(path, "*.*")); + while(ff) { + String nm = ff.GetName(); + String s = AppendFileName(path, nm); + String t = AppendFileName(tp, nm); + if(ff.IsFolder()) + if(nm == ".svn") + FileMove(s, t); + else + MoveSvn(s, t); + ff.Next(); + } +} + +void SvnSync::DoSync() +{ + SyncList(); + if(Execute() != IDOK || list.GetCount() == 0) + return; + SysConsole sys; + int repoi = 0; + int i = 0; + while(i < list.GetCount()) { + SvnWork w = works[repoi++]; + i++; + String message; + while(i < list.GetCount()) { + int action = list.Get(i, 0); + String path = list.Get(i, 1); + if(action == MESSAGE) { + sys.System(SvnCmd("commit", w).Cat() << w.working << " -m \"" << list.Get(i, 3) << "\""); + i++; + break; + } + if(action == REPOSITORY) + break; + switch(action) { + case ADD: + SvnDel(path); + sys.System("svn add --force " + path); + break; + case REMOVE: + sys.System("svn delete " + path); + break; + case CONFLICT: + sys.System("svn resolved " + path); + break; + case REPLACE: { + String tp = AppendFileName(GetFileFolder(path), Format(Uuid::Create())); + FileMove(path, tp); + sys.System(SvnCmd("update", w).Cat() << ' ' << path); + MoveSvn(path, tp); + sDeleteFolderDeep(path); + FileMove(tp, path); + Vector ln = Split(Sys("svn status " + path), CharFilterCrLf); + for(int i = 0; i < ln.GetCount(); i++) { + String h = ln[i]; + if(h.GetCount() > 7) { + String file = h.Mid(7); + if(IsFullPath(file)) { + h.Trim(7); + if(h == "? ") + sys.System("svn add --force " + file); + if(h == "! ") + sys.System("svn delete " + file); + } + } + } + } + break; + } + i++; + } + sys.System(SvnCmd("update", w).Cat() << w.working); + } + sys.Perform(); +} + +#ifdef flagMAIN +GUI_APP_MAIN +{ +// SvnSel svn; +// svn.Select(); +// svn.Select("svn://10.0.0.19/upp", "", ""); +// return; + + SvnSync().Perform(); +} +#endif diff --git a/uppsrc/usvn/usvn.h b/uppsrc/usvn/usvn.h index 66806dbee..4cc1e9df4 100644 --- a/uppsrc/usvn/usvn.h +++ b/uppsrc/usvn/usvn.h @@ -1,124 +1,125 @@ -#ifndef _usvn_usvn_h_ -#define _usvn_usvn_h_ - -#include - -using namespace Upp; - -#include "SlaveProcess.h" - -#define LAYOUTFILE -#include - -class SysConsole : public WithConsoleLayout { - typedef SysConsole CLASSNAME; - - Font font; - void AddResult(const String& out); - -public: - int System(const char *s); - void Perform() { exit.Show(); Execute(); } - - SysConsole(); -}; - -class SvnSel : public WithSvnSelLayout { - String url, usr, pwd; - String folder; - - bool Load(const String& path); - void SyncResult(); - void Go(); - void DirUp(); - bool NewUrl(); - void Url(); - bool TryLoad(const char *url); - bool Select0(); - - typedef SvnSel CLASSNAME; - -public: - bool Select(); - bool Select(const char *url, const char *user, const char *pwd); - - String GetUsername() const { return usr; } - String GetPassword() const { return pwd; } - String GetUrl() const { return ~result; } - - SvnSel(); -}; - -struct Repo { - String repo; - String work; - String user; - String pswd; - - void Save(String& s); - void Load(CParser& p); -}; - -struct SvnWork { - String working; - String user; - String password; -}; - -class SvnWorks : public WithSvnWorksLayout { - void New(); - void Edit(); - void Remove(); - void Checkout(); - void Sync(); - - FrameRight