# # patch "main.cc" # from [a60b92b85a3e6e0b8537d79149f679dd0224ad19] # to [1f179a25ce2dee322306ade507812ccd0c7de8f5] # # patch "misc.cc" # from [b48e0890f3fea8bcfa4286d11bbc9b91ea6bb974] # to [b632c3e08a89ac9a0045af913319d5e68e8444a1] # # patch "misc.hh" # from [57670910b8220d95d01341207829aad9e194706d] # to [13e5b8e9966be45be74a07dfddff8c730f2304a0] # # patch "monotone.cc" # from [a738042de602184b65c94272e2913e4ca4835d31] # to [71a4d5c7f44e1c0834efcda59ca776c8501ae66e] # # patch "monotone.hh" # from [87cf2c03ca9f43cffac94aadf90b022f7d495650] # to [faca8a5452650ddac597dcd331d3587d34f99aff] # ======================================================================== --- main.cc a60b92b85a3e6e0b8537d79149f679dd0224ad19 +++ main.cc 1f179a25ce2dee322306ade507812ccd0c7de8f5 @@ -76,6 +76,8 @@ void sync() { + SyncDialog sd(mtn); + sd.run(); } void setdb() @@ -159,11 +161,11 @@ sigc::mem_fun(*this, &mainwin::quit)); ag->add(Gtk::Action::create("File_menu", "_File")); ag->add(Gtk::Action::create("Work_menu", "_Working dir")); -// ag->add(Gtk::Action::create("Database_menu", "_Database")); + ag->add(Gtk::Action::create("Database_menu", "_Database")); ag->add(Gtk::Action::create("Update", Gtk::Stock::GO_UP, "Update"), sigc::mem_fun(*this, &mainwin::update)); -// ag->add(Gtk::Action::create("Sync", Gtk::Stock::NETWORK, "Sync"), -// sigc::mem_fun(*this, &mainwin::sync)); + ag->add(Gtk::Action::create("Sync", Gtk::Stock::NETWORK, "Sync"), + sigc::mem_fun(*this, &mainwin::sync)); ui = Gtk::UIManager::create(); ui->insert_action_group(ag); Glib::ustring cmdxml = @@ -180,9 +182,9 @@ " " " " " " -// " " -// " " -// " " + " " + " " + " " " " " " " " ======================================================================== --- misc.cc b48e0890f3fea8bcfa4286d11bbc9b91ea6bb974 +++ misc.cc b632c3e08a89ac9a0045af913319d5e68e8444a1 @@ -1,4 +1,5 @@ #include "misc.hh" +#include "monotone.hh" #include #include @@ -44,3 +45,51 @@ Gtk::TreeModel::Row r = *store->get_iter(p); return Glib::ustring(r[col.name]); } + +namespace { + SyncDialog *sd; + void sd_lwcb() + { + int r = sd->output.rfind("\r"); + int n = sd->output.rfind("\n", r); + if (r != string::npos && n != string::npos) + sd->output = sd->output.substr(0, n+1) + sd->output.substr(r+1); + Glib::RefPtr b = sd->tv.get_buffer(); + b->set_text(sd->output); + Glib::RefPtr t = b->create_tag(); + t->property_family() = "monospace"; + b->apply_tag(t, b->begin(), b->end()); + while (Gtk::Main::events_pending()) + Gtk::Main::iteration(); + } +}; + +// mtn->sync() is called from a timeout so that we'll return first, +// and it will be called from the event loop, *after* our window exists, +// and can continue to run the event loop itself. +SyncDialog::SyncDialog(monotone & m) + : mtn(&m), prev_lwcb(m.get_longwait_callback()) +{ + get_vbox()->add(tv); + tv.set_editable(false); + get_vbox()->show_all_children(); + cancelbtn = add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); + okbtn = add_button("Done", Gtk::RESPONSE_OK); + okbtn->set_sensitive(false); + sd = this; + mtn->set_longwait_callback(sd_lwcb); + Glib::signal_timeout().connect(sigc::mem_fun(this, &SyncDialog::timer), 0); +} + +SyncDialog::~SyncDialog() +{ + mtn->set_longwait_callback(prev_lwcb); +} + +bool SyncDialog::timer() +{ + mtn->sync(output); + okbtn->set_sensitive(true); + cancelbtn->set_sensitive(false); + return false; +} ======================================================================== --- misc.hh 57670910b8220d95d01341207829aad9e194706d +++ misc.hh 13e5b8e9966be45be74a07dfddff8c730f2304a0 @@ -5,6 +5,8 @@ #include #include +using std::string; +using std::vector; std::string readfile(std::string const & f); @@ -23,4 +25,18 @@ std::string result(); }; +struct monotone; + +struct SyncDialog : public Gtk::Dialog +{ + monotone *mtn; + Gtk::Button *okbtn, *cancelbtn; + Gtk::TextView tv; + void(*prev_lwcb)(); + string output; + SyncDialog(monotone & m); + ~SyncDialog(); + bool timer(); +}; + #endif ======================================================================== --- monotone.cc a738042de602184b65c94272e2913e4ca4835d31 +++ monotone.cc 71a4d5c7f44e1c0834efcda59ca776c8501ae66e @@ -22,7 +22,7 @@ inline int max(int a, int b) {return (a>b)?a:b;} -monotone::monotone(): pid(-1), lwcb(0) +monotone::monotone(): pid(-1), dir("."), lwcb(0) { } @@ -204,9 +204,15 @@ i != args.end(); ++i) s << i->size() << ":" << *i; std::string c = "l" + s.str() + "e"; + try { write(to, c.c_str(), c.size()); while(!stopped() && read_packet(res)) ; + } catch (std::exception &) { + // something bad happened, assume the monotone process is ****ed up + stop(); + return std::string(); + } return res; } @@ -261,6 +267,7 @@ monotone::inventory(std::vector & out) { out.clear(); + try { std::vector args; std::string res = command("inventory", args); std::map renames; @@ -348,6 +355,7 @@ begin = end + 1; end = res.find('\n', begin); } + } catch (std::exception &) {/*maybe find a way to indicate an error?*/} } std::vector monotone::certs(std::string const & rev) @@ -553,3 +561,12 @@ args.push_back("--revision="+rev); runcmd("update", args, ign, err); } + +void +monotone::sync(string & res) +{ + string ign; + vector args; + args.push_back("--ticker=count"); + runcmd("sync", args, ign, res); +} ======================================================================== --- monotone.hh 87cf2c03ca9f43cffac94aadf90b022f7d495650 +++ monotone.hh faca8a5452650ddac597dcd331d3587d34f99aff @@ -13,6 +13,8 @@ #include #include +using std::string; +using std::vector; struct inventory_item @@ -57,7 +59,8 @@ monotone(); ~monotone(); void set_longwait_callback(longwait_callback lc); - void set_dir(std::string const & s){dir = s; stop();} + longwait_callback get_longwait_callback(){return lwcb;} + void set_dir(std::string const & s){dir = (s.empty()?".":s); stop();} void set_db(std::string const & s){db = s; stop();} std::string get_dir(){return dir;} std::string get_db(){return db;} @@ -90,6 +93,7 @@ void rename(std::string const & oldname, std::string const & newname); bool update(std::vector & opts); void update(std::string const & rev); + void sync(string & res); }; #endif