# # patch "main.cc" # from [a2bdece7e2dc34b1f5234d80cb3b5cfc85508d37] # to [0203c798531c12adf0e75354c7c1811bf95c09bf] # # patch "misc.cc" # from [68edf20d814043ff880d554c599e8976d1c549a4] # to [b48e0890f3fea8bcfa4286d11bbc9b91ea6bb974] # # patch "misc.hh" # from [b7f219290cb6c208ce0cd5792067ca0e7b975d6b] # to [57670910b8220d95d01341207829aad9e194706d] # # patch "monotone.cc" # from [522a62873dc929e9fbe237fcf5def1a101d0ee6e] # to [3119182ccd47b15467fb05e68c94a08914efbeb1] # # patch "monotone.hh" # from [10fca34cd009536a4ff5de023a1aba6acfa5343e] # to [0c12a29da47fe9c6ec1f234ce9cd9fc6abe1e30a] # # patch "rev_file_list.cc" # from [1b1e098f3ead04924aaee9a8dd872be81f246b5f] # to [2780a7a19841e6588e6179a34ee1e44758c85c20] # # patch "rev_file_list.hh" # from [fbc3f04ddf9cef65a04c4a93d5761ecf866f3540] # to [83d9b4f851f84e531febf8978fe0f37bdf8c5cab] # # patch "revdat.cc" # from [37cd8ddb2178510d21d6365a84c91786a1433006] # to [5ff666d9031ab8c1df0ef13886667ed9fae5a3b1] # # patch "revdat.hh" # from [2924a24894a0e92192bbfa3076f2d9a56146fe0f] # to [33496a7d49f91e2dafff4d220388ddd84176e856] # ======================================================================== --- main.cc a2bdece7e2dc34b1f5234d80cb3b5cfc85508d37 +++ main.cc 0203c798531c12adf0e75354c7c1811bf95c09bf @@ -14,6 +14,7 @@ #include "monotone.hh" #include "revdat.hh" +#include "misc.hh" // The toolbar generator doesn't understand this kind of item. // [Text entry here] [Go!] @@ -51,6 +52,26 @@ txt_toolitem ti; public: + void update() + { + std::vector rr; + if (!mtn.update(rr)) + { + chooser c(rr); + int result = c.run(); + if (result == Gtk::RESPONSE_OK) + { + std::string rev = c.result(); + if (!rev.empty()) + mtn.update(rev); + } + } + } + + void sync() + { + } + void setdb() { Gtk::FileChooserDialog dialog("Please choose a database", @@ -70,7 +91,7 @@ if (result == Gtk::RESPONSE_OK) { mtn.set_db(dialog.get_filename()); - do_refresh(); + rd.clear(); } } void setdir() @@ -85,7 +106,7 @@ { mtn.set_dir(dialog.get_filename()); chdir(dialog.get_filename().c_str()); - do_refresh(); + rd.loadwork(); } } void do_refresh() @@ -129,13 +150,34 @@ sigc::mem_fun(*this, &mainwin::do_commit)); ag->add(Gtk::Action::create("Quit", Gtk::Stock::QUIT), 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("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)); ui = Gtk::UIManager::create(); ui->insert_action_group(ag); Glib::ustring cmdxml = "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " +// " " +// " " +// " " + " " " " - " " - " " " " " " " " @@ -148,7 +190,8 @@ (ui->get_widget("/Toolbar")); ti.button.signal_clicked().connect(sigc::mem_fun(*this, &mainwin::to_rev)); ti.entry.signal_activate().connect(sigc::mem_fun(*this, &mainwin::to_rev)); - tb->insert(ti, 3); + tb->insert(ti, 1); + stuff.pack_start(*ui->get_widget("/Menubar"), Gtk::PACK_SHRINK); stuff.pack_start(*tb, Gtk::PACK_SHRINK); stuff.pack_end(rd); add(stuff); ======================================================================== --- misc.cc 68edf20d814043ff880d554c599e8976d1c549a4 +++ misc.cc b48e0890f3fea8bcfa4286d11bbc9b91ea6bb974 @@ -18,3 +18,29 @@ } return out; } + +chooser::chooser(std::vector const & options) + : store(Gtk::ListStore::create(col)), view(store) +{ + view.append_column("Choose one...", col.name); + get_vbox()->add(view); + view.show(); + for (std::vector::const_iterator i = options.begin(); + i != options.end(); ++i) + { + Gtk::ListStore::Row row = *store->append(); + row[col.name] = *i; + } + add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); + add_button("Select", Gtk::RESPONSE_OK); +} + +std::string +chooser::result() +{ + Gtk::TreeModel::Path p; + Gtk::TreeViewColumn *c; + view.get_cursor(p, c); + Gtk::TreeModel::Row r = *store->get_iter(p); + return Glib::ustring(r[col.name]); +} ======================================================================== --- misc.hh b7f219290cb6c208ce0cd5792067ca0e7b975d6b +++ misc.hh 57670910b8220d95d01341207829aad9e194706d @@ -1,8 +1,26 @@ #ifndef __MISC_HH__ #define __MISC_HH__ +#include + +#include #include std::string readfile(std::string const & f); +class chooser: public Gtk::Dialog +{ + struct cols: public Gtk::TreeModel::ColumnRecord + { + Gtk::TreeModelColumn name; + cols() {add(name);} + }; + cols col; + Glib::RefPtr store; + Gtk::TreeView view; +public: + chooser(std::vector const & options); + std::string result(); +}; + #endif ======================================================================== --- monotone.cc 522a62873dc929e9fbe237fcf5def1a101d0ee6e +++ monotone.cc 3119182ccd47b15467fb05e68c94a08914efbeb1 @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -30,7 +31,8 @@ { int to_mtn[2]; int from_mtn[2]; - if (pipe(to_mtn) < 0 || pipe(from_mtn) < 0) + int err_mtn[2]; + if (pipe(to_mtn) < 0 || pipe(from_mtn) < 0 || pipe(err_mtn) < 0) return false; pid = fork(); if (pid < 0) @@ -39,14 +41,18 @@ close(to_mtn[1]); close(from_mtn[0]); close(from_mtn[1]); + close(err_mtn[0]); + close(err_mtn[1]); return false; } else if (pid > 0) { close(to_mtn[0]); close(from_mtn[1]); + close(err_mtn[1]); to = to_mtn[1]; from = from_mtn[0]; + errfrom = err_mtn[0]; return true; } else @@ -56,10 +62,11 @@ chdir(dir.c_str()); if (close(to_mtn[1]) < 0 || close(from_mtn[0]) < 0) return false; - if (close(0) < 0 || close(1) < 0) + if (close(0) < 0 || close(1) < 0 || close(2) < 0) return false; -// close(2); - if (dup2(to_mtn[0], 0) < 0 || dup2(from_mtn[1], 1) < 0) + if (dup2(to_mtn[0], 0) < 0 + || dup2(from_mtn[1], 1) < 0 + || dup2(err_mtn[1], 2) < 0) return false; char **arg = new char *[args.size() + 2]; arg[0] = "monotone"; @@ -189,11 +196,14 @@ ; return res; } -std::string + +void monotone::runcmd(std::string const & cmd, - std::vector const & args) + std::vector const & args, + std::string & out, std::string & err) { - std::string out; + out.clear(); + err.clear(); stop();// stop stdio std::vector argg = args; argg.insert(argg.begin(), cmd); @@ -201,15 +211,34 @@ int size = 2048; char *output = new char[size]; - int r = 0; + char *errout = new char[size]; + fd_set rd, ex; do { - out += std::string(output, r); - r = read(from, output, size); - } while (r >= 0 && !stopped()); + FD_ZERO(&rd); + FD_ZERO(&ex); + FD_SET(from, &rd); + FD_SET(errfrom, &rd); + FD_SET(from, &ex); + FD_SET(errfrom, &ex); + int s = ::select(max(from, errfrom)+1, &rd, 0, &ex, 0); + if (FD_ISSET(from, &rd)) + { + int r = read(from, output, size); + out += std::string(output, r); + } + if (FD_ISSET(errfrom, &rd)) + { + int r = read(errfrom, errout, size); + err += std::string(errout, r); + } + } while (!stopped()); + int r = read(from, output, size); + out += std::string(output, r); + r = read(errfrom, errout, size); + err += std::string(errout, r); delete[] output; - - return out; + delete[] errout; } void @@ -375,12 +404,14 @@ args.push_back(rev); args.push_back(name); args.push_back(value); - runcmd("cert", args); + std::string ign1, ign2; + runcmd("cert", args, ign1, ign2); } std::string monotone::commit(std::vector args) { - runcmd("commit", args); + std::string ign1, ign2; + runcmd("commit", args, ign1, ign2); args.clear(); std::string res = command("get_revision", args); for (int begin = 0, end = res.find('\n'); begin != res.size(); @@ -398,9 +429,11 @@ std::string monotone::diff(std::string const & filename) { + std::string out, ign; std::vector args; args.push_back(filename); - return runcmd("diff", args); + runcmd("diff", args, out, ign); + return out; } std::string monotone::diff(std::string const & filename, @@ -411,7 +444,9 @@ args.push_back(filename); args.push_back("--revision=" + rev1); args.push_back("--revision=" + rev2); - return runcmd("diff", args); + std::string out, ign; + runcmd("diff", args, out, ign); + return out; } std::string monotone::cat(std::string const & filename, std::string const & rev) @@ -419,7 +454,9 @@ std::vector args; args.push_back(filename); args.push_back("--revision=" + rev); - return runcmd("cat", args); + std::string out, ign; + runcmd("cat", args, out, ign); + return out; } std::string monotone::get_revision(std::string const & rev) @@ -438,29 +475,64 @@ void monotone::add(std::string const & file) { + std::string ign1, ign2; std::vector args; args.push_back(file); - runcmd("add", args); + runcmd("add", args, ign1, ign2); } void monotone::drop(std::string const & file) { + std::string ign1, ign2; std::vector args; args.push_back(file); - runcmd("drop", args); + runcmd("drop", args, ign1, ign2); } void monotone::revert(std::string const & file) { + std::string ign1, ign2; std::vector args; args.push_back(file); - runcmd("revert", args); + runcmd("revert", args, ign1, ign2); } void monotone::rename(std::string const & oldname, std::string const & newname) { + std::string ign1, ign2; std::vector args; args.push_back(oldname); args.push_back(newname); - runcmd("rename", args); + runcmd("rename", args, ign1, ign2); } + +bool +monotone::update(std::vector & opts) +{ + opts.clear(); + std::string ign, err; + std::vector args; + runcmd("update", args, ign, err); + int p = err.find("multiple update candidates"); + if (p == std::string::npos) + return true; + + p = err.find("monotone: ", p + 1); + while (p != std::string::npos) + { + p = err.find(":", p); + p = err.find_first_not_of(" ", p + 1); + opts.push_back(err.substr(p, 40)); + p = err.find("monotone: ", p + 1); + } + return false; +} + +void +monotone::update(std::string const & rev) +{ + std::string ign, err; + std::vector args; + args.push_back("--revision="+rev); + runcmd("update", args, ign, err); +} ======================================================================== --- monotone.hh 10fca34cd009536a4ff5de023a1aba6acfa5343e +++ monotone.hh 0c12a29da47fe9c6ec1f234ce9cd9fc6abe1e30a @@ -41,6 +41,7 @@ std::string dir;// chdir here before exec std::string db;// if not empty, add --db= to argument list for exec int from; + int errfrom; int to; bool execute(std::vector args); @@ -61,8 +62,9 @@ std::string command(std::string const & cmd, std::vector const & args); // run a command from the command line - std::string runcmd(std::string const & cmd, - std::vector const & args); + void runcmd(std::string const & cmd, + std::vector const & args, + std::string & out, std::string & err); void inventory(std::vector & out); std::vector certs(std::string const & rev); @@ -82,6 +84,8 @@ void drop(std::string const & file); void revert(std::string const & file); void rename(std::string const & oldname, std::string const & newname); + bool update(std::vector & opts); + void update(std::string const & rev); }; #endif ======================================================================== --- rev_file_list.cc 1b1e098f3ead04924aaee9a8dd872be81f246b5f +++ rev_file_list.cc 2780a7a19841e6588e6179a34ee1e44758c85c20 @@ -279,7 +279,10 @@ void rev_file_list::set_rev(std::string const & r) { rev = r; - certs = rd->mtn->certs(r); + if (r.empty()) + certs.clear(); + else + certs = rd->mtn->certs(r); } void rev_file_list::pchange(int n) ======================================================================== --- rev_file_list.hh fbc3f04ddf9cef65a04c4a93d5761ecf866f3540 +++ rev_file_list.hh 83d9b4f851f84e531febf8978fe0f37bdf8c5cab @@ -108,9 +108,9 @@ void menuundrop(); void menurevert(); - void rev_file_list::drag_get(const Glib::RefPtr & dc, - Gtk::SelectionData& sel_data, - guint a, guint b); + void drag_get(const Glib::RefPtr & dc, + Gtk::SelectionData& sel_data, + guint a, guint b); void dosel(Gtk::TreeModel::Path const & p); bool selchanged(Glib::RefPtr const & model, ======================================================================== --- revdat.cc 37cd8ddb2178510d21d6365a84c91786a1433006 +++ revdat.cc 5ff666d9031ab8c1df0ef13886667ed9fae5a3b1 @@ -190,6 +190,15 @@ rfl.set_files(res); } +void revdat::clear() +{ + rfl.set_wc(false); + rfl.set_rev(""); + std::vector pvec; + std::vector > pchanges; + rfl.set_parents(pvec, pchanges); +} + void revdat::loadrev(std::string const & rev) { revision = rev; ======================================================================== --- revdat.hh 2924a24894a0e92192bbfa3076f2d9a56146fe0f +++ revdat.hh 33496a7d49f91e2dafff4d220388ddd84176e856 @@ -31,6 +31,7 @@ std::string get_rev(){return rfl.get_rev();} bool get_wc(){return rfl.get_wc();} void loadrev(std::string const & rev); + void clear(); }; #endif