Hand-apply d4470377df181b4d15fbac86c454a8372b1a0f3d; fix update checker.
authorCarl Hetherington <cth@carlh.net>
Sat, 24 Jan 2015 00:12:45 +0000 (00:12 +0000)
committerCarl Hetherington <cth@carlh.net>
Sat, 24 Jan 2015 00:12:45 +0000 (00:12 +0000)
ChangeLog
src/lib/update.cc
src/lib/update.h
src/lib/util.h
src/tools/dcpomatic.cc
src/wx/update_dialog.cc
src/wx/update_dialog.h
test/update_checker_test.cc [new file with mode: 0644]
test/wscript

index b321f4bf1510d84806ab5ce685770df744f03e87..710fa3fafaa26c8a527a064646e125a740ce32b8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
 2015-01-23  Carl Hetherington  <cth@carlh.net>
 
+       * Fix update checker.
+
        * Scan a whole FFmpeg file if no duration is given
        in its header.
 
index c50022091fbe3ab6abb0169e86fa00e7444c4cb3..b41d8bb66d1dfb7e47b74a5bbc7a15eb988614ce 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 #include "version.h"
 #include "ui_signaller.h"
 #include "safe_stringstream.h"
+#include "config.h"
+#include "util.h"
 
 #define BUFFER_SIZE 1024
 
 using std::cout;
 using std::min;
 using std::string;
+using std::vector;
 using dcp::raw_convert;
+using boost::is_any_of;
+using boost::ends_with;
 
 /** Singleton instance */
 UpdateChecker* UpdateChecker::_instance = 0;
@@ -115,26 +120,27 @@ UpdateChecker::thread ()
                        string s (_buffer);
                        cxml::Document doc ("Update");
                        doc.read_string (s);
-                       
+
+                       /* Read the current stable and test version numbers */
+
+                       string stable;
+                       string test;
+
                        {
                                boost::mutex::scoped_lock lm (_data_mutex);
-                               _stable = doc.string_child ("Stable");
-                               _test = doc.string_child ("Test");
+                               stable = doc.string_child ("Stable");
+                               test = doc.string_child ("Test");
                        }
-                       
-                       string current = string (dcpomatic_version);
-                       bool current_pre = false;
-                       if (boost::algorithm::ends_with (current, "pre")) {
-                               current = current.substr (0, current.length() - 3);
-                               current_pre = true;
+
+                       if (version_less_than (dcpomatic_version, stable)) {
+                               _stable = stable;
                        }
                        
-                       float current_float = raw_convert<float> (current);
-                       if (current_pre) {
-                               current_float -= 0.005;
+                       if (Config::instance()->check_for_test_updates() && version_less_than (dcpomatic_version, test)) {
+                               _test = test;
                        }
-                       
-                       if (current_float < raw_convert<float> (_stable)) {
+
+                       if (_stable || _test) {
                                set_state (YES);
                        } else {
                                set_state (NO);
@@ -176,4 +182,36 @@ UpdateChecker::instance ()
        return _instance;
 }
 
+bool
+UpdateChecker::version_less_than (string const & a, string const & b)
+{
+       vector<string> ap;
+       split (ap, a, is_any_of ("."));
+       vector<string> bp;
+       split (bp, b, is_any_of ("."));
+
+       DCPOMATIC_ASSERT (ap.size() == 3 && bp.size() == 3);
+
+       if (ap[0] != bp[0]) {
+               return raw_convert<int> (ap[0]) < raw_convert<int> (bp[0]);
+       }
+
+       if (ap[1] != bp[1]) {
+               return raw_convert<int> (ap[1]) < raw_convert<int> (bp[1]);
+       }
+       float am;
+       if (ends_with (ap[2], "devel")) {
+               am = raw_convert<int> (ap[2].substr (0, ap[2].length() - 5)) + 0.5;
+       } else {
+               am = raw_convert<int> (ap[2]);
+       }
+       
+       float bm;
+       if (ends_with (bp[2], "devel")) {
+               bm = raw_convert<int> (bp[2].substr (0, bp[2].length() - 5)) + 0.5;
+       } else {
+               bm = raw_convert<int> (bp[2]);
+       }
        
+       return am < bm;
+}
index f3a0ffc36f55498dc1046f0268164641af1e09df..c3e2b5613d2772e3049f1c685d3e7c86aab71e27 100644 (file)
@@ -27,6 +27,8 @@
 #include <boost/thread/condition.hpp>
 #include <boost/thread.hpp>
 
+struct update_checker_test;
+
 /** Class to check for the existance of an update for DCP-o-matic on a remote server */
 class UpdateChecker
 {
@@ -49,14 +51,14 @@ public:
                return _state;
        }
        
-       /** @return the version string of the latest stable version (if _state == YES or NO) */
-       std::string stable () {
+       /** @return new stable version, if there is one */
+       boost::optional<std::string> stable () {
                boost::mutex::scoped_lock lm (_data_mutex);
                return _stable;
        }
 
-       /** @return the version string of the latest test version (if _state == YES or NO) */
-       std::string test () {
+       /** @return new test version, if there is one and Config is set to look for it */
+       boost::optional<std::string> test () {
                boost::mutex::scoped_lock lm (_data_mutex);
                return _test;
        }
@@ -73,9 +75,13 @@ public:
 
        static UpdateChecker* instance ();
 
-private:       
+private:
+       friend struct update_checker_test;
+       
        static UpdateChecker* _instance;
 
+       static bool version_less_than (std::string const & a, std::string const & b);
+
        void set_state (State);
        void thread ();
 
@@ -86,8 +92,8 @@ private:
        /** mutex to protect _state, _stable, _test and _emits */
        mutable boost::mutex _data_mutex;
        State _state;
-       std::string _stable;
-       std::string _test;
+       boost::optional<std::string> _stable;
+       boost::optional<std::string> _test;
        int _emits;
 
        boost::thread* _thread;
index 9ae149ef4cd76a8e79583a6f73ab05658d098077..b06c8a58b5e8b5f78ac33314261d8c3f6024212a 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
index 6d27a4248cda0f2b3cb07fc031c1f24620d11eb7..614073947b4032e305ef26a0a2e90c1879f740a5 100644 (file)
@@ -896,29 +896,19 @@ class App : public wxApp
 
        void update_checker_state_changed ()
        {
-               switch (UpdateChecker::instance()->state ()) {
-               case UpdateChecker::YES:
-               {
-                       string test;
-                       if (Config::instance()->check_for_test_updates ()) {
-                               test = UpdateChecker::instance()->test ();
-                       }
-                       UpdateDialog* dialog = new UpdateDialog (_frame, UpdateChecker::instance()->stable (), test);
+               UpdateChecker* uc = UpdateChecker::instance ();
+               if (uc->state() == UpdateChecker::YES && (uc->stable() || uc->test())) {
+                       UpdateDialog* dialog = new UpdateDialog (_frame, uc->stable (), uc->test ());
                        dialog->ShowModal ();
                        dialog->Destroy ();
-                       break;
-               }
-               case UpdateChecker::NO:
+               } else if (uc->state() == UpdateChecker::FAILED) {
                        if (!UpdateChecker::instance()->last_emit_was_first ()) {
-                               error_dialog (_frame, _("There are no new versions of DCP-o-matic available."));
+                               error_dialog (_frame, _("The DCP-o-matic download server could not be contaced."));
                        }
-                       break;
-               case UpdateChecker::FAILED:
+               } else {
                        if (!UpdateChecker::instance()->last_emit_was_first ()) {
-                               error_dialog (_frame, _("The DCP-o-matic download server could not be contacted."));
+                               error_dialog (_frame, _("There are no new versions of DCP-o-matic available."));
                        }
-               default:
-                       break;
                }
        }
 
index 271c4174c611a441197c889a0dd9a081b490fba1..c8c90d86e499a22b0ea44ba5716ffa8578cac7f2 100644 (file)
 #include "wx_util.h"
 
 using std::string;
+using boost::optional;
 
-UpdateDialog::UpdateDialog (wxWindow* parent, string stable, string test)
+UpdateDialog::UpdateDialog (wxWindow* parent, optional<string> stable, optional<string> test)
        : wxDialog (parent, wxID_ANY, _("Update"))
 {
        wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
 
        wxStaticText* message;
 
-       if (test.empty ()) {
+       if ((stable || test) && !(stable && test)) {
                message = new wxStaticText (this, wxID_ANY, _("A new version of DCP-o-matic is available."));
        } else {
                message = new wxStaticText (this, wxID_ANY, _("New versions of DCP-o-matic are available."));
@@ -40,17 +41,19 @@ UpdateDialog::UpdateDialog (wxWindow* parent, string stable, string test)
 
        wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
 
-       add_label_to_sizer (table, this, _("Stable version ") + std_to_wx (stable), true);
-       wxHyperlinkCtrl* h = new wxHyperlinkCtrl (this, wxID_ANY, "dcpomatic.com/download", "http://dcpomatic.com/download");
-       table->Add (h);
+       if (stable) {
+               add_label_to_sizer (table, this, _("Stable version ") + std_to_wx (stable.get ()), true);
+               wxHyperlinkCtrl* h = new wxHyperlinkCtrl (this, wxID_ANY, "dcpomatic.com/download", "http://dcpomatic.com/download");
+               table->Add (h);
+       }
        
-       if (!test.empty ()) {
-               add_label_to_sizer (table, this, _("Test version ") + std_to_wx (test), true);
+       if (test) {
+               add_label_to_sizer (table, this, _("Test version ") + std_to_wx (test.get ()), true);
                wxHyperlinkCtrl* h = new wxHyperlinkCtrl (this, wxID_ANY, "dcpomatic.com/test-download", "http://dcpomatic.com/test-download");
                table->Add (h);
        }
        
-       overall_sizer->Add (table, 1, wxEXPAND | wxLEFT | wxRIGHT, DCPOMATIC_DIALOG_BORDER);
+       overall_sizer->Add (table, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, DCPOMATIC_DIALOG_BORDER);
 
        wxSizer* buttons = CreateButtonSizer (wxOK);
        if (buttons) {
index d9c7b855d96012c01fb8b7479df0a9d189c74ac4..e9ea28cad9f047eb2cb342bd7d12fc7f940709ae 100644 (file)
 */
 
 #include <wx/wx.h>
+#include <boost/optional.hpp>
 
 class UpdateDialog : public wxDialog
 {
 public:
-       UpdateDialog (wxWindow *, std::string, std::string);
+       UpdateDialog (wxWindow *, boost::optional<std::string>, boost::optional<std::string>);
 };
 
diff --git a/test/update_checker_test.cc b/test/update_checker_test.cc
new file mode 100644 (file)
index 0000000..c9a4499
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/test/unit_test.hpp>
+#include "lib/update.h"
+
+BOOST_AUTO_TEST_CASE (update_checker_test)
+{
+       BOOST_CHECK (UpdateChecker::version_less_than ("0.0.1", "0.0.2"));
+       BOOST_CHECK (UpdateChecker::version_less_than ("1.0.1", "2.0.2"));
+       BOOST_CHECK (UpdateChecker::version_less_than ("0.1.1", "1.5.2"));
+       BOOST_CHECK (UpdateChecker::version_less_than ("1.9.45", "1.9.46"));
+
+       BOOST_CHECK (!UpdateChecker::version_less_than ("0.0.1", "0.0.1"));
+       BOOST_CHECK (!UpdateChecker::version_less_than ("2.0.2", "1.0.1"));
+       BOOST_CHECK (!UpdateChecker::version_less_than ("1.5.2", "0.1.1"));
+       BOOST_CHECK (!UpdateChecker::version_less_than ("1.9.46", "1.9.45"));
+
+       BOOST_CHECK (!UpdateChecker::version_less_than ("1.9.46devel", "1.9.46"));
+}
index cf3481dc56c03b8e93311e971f0968d7b15cb1c0..1333dc6545ff29904a66b3879ea8dcaad29b62dd 100644 (file)
@@ -57,6 +57,7 @@ def build(bld):
                  stream_test.cc
                  test.cc
                  threed_test.cc
+                 update_checker_test.cc
                  upmixer_a_test.cc
                  util_test.cc
                  video_decoder_fill_test.cc