Commits

Anonymous committed 009c38c

Factor out retry facility into a utility function. Add unit tests. Retry on svn status as well if --svn-retry is set.

Comments (0)

Files changed (4)

     except ExternalCommandFailed, err:
         pass
     return False
+
+def once_or_more(desc, retry, function, *args, **kwargs):
+    """Try executing the provided function at least once.
+
+    If ``retry`` is ``True``, running the function with the given arguments
+    if an ``Exception`` is raised. Otherwise, only run the function once.
+
+    The string ``desc`` should be set to a short description of the operation.
+    """
+    while True:
+        try:
+            return function(*args, **kwargs)
+        except Exception, e:
+            ui.status('%s failed: %s', desc, str(e))
+            if retry:
+                ui.status('Trying %s again...', desc)
+                continue
+            else:
+                raise

hgsvn/run/hgpullsvn.py

     hg_commit_from_svn_log_entry, hg_exclude_options,
     get_svn_rev_from_hg, hg_switch_branch, hg_is_clean,
     check_for_applied_patches,
+    once_or_more,
 )
 from hgsvn.svnclient import (
     get_svn_info, get_svn_versioned_files, iter_svn_log_entries, run_svn_log,
             if get_svn_client_version() >= (1, 5):
                 args.extend(['--accept', 'postpone'])
             ui.status('Attempting to update to revision %s...', str(svn_rev))
-            # We wrap the svn update invocation in a loop so it can
-            # re-execute on failure if the --svn-retry option is set.
-            while True:
-                try:
-                    run_svn(args + ["-r", svn_rev, svn_wc])
-                    break
-                except Exception, e:
-                    ui.status('SVN update failed: %s', str(e))
-                    if retry:
-                        ui.status('Trying to update again...')
-                        continue
-                    else:
-                        raise
+            once_or_more("SVN update", retry, run_svn, args + ["-r", svn_rev, svn_wc])
             conflicts = []
             for status_entry in get_svn_status('.'):
                 if status_entry['status'] == 'conflicted':
         run_hg(["update", "-C", "svn.%d" % current_rev])
 
     # Load SVN log starting from current rev
-    it_log_entries = iter_svn_log_entries(svn_peg_wc, next_rev, svn_greatest_rev)
+    it_log_entries = iter_svn_log_entries(svn_peg_wc, next_rev, svn_greatest_rev, options.svnretry)
 
     try:
         try:

hgsvn/svnclient.py

 
 from hgsvn import ui
-from hgsvn.common import run_svn
+from hgsvn.common import (run_svn, once_or_more)
 from hgsvn.errors import EmptySVNLog
 
 import os
 log_duration_threshold = 10.0
 log_min_chunk_length = 10
 
-def iter_svn_log_entries(svn_url, first_rev, last_rev):
+def iter_svn_log_entries(svn_url, first_rev, last_rev, retry):
     """
     Iterate over SVN log entries between first_rev and last_rev.
 
         stop_rev = min(last_rev, cur_rev + int(chunk_length * chunk_interval_factor))
         ui.status("Fetching SVN log for revisions %d-%d...", cur_rev, stop_rev,
                   level=ui.VERBOSE)
-        entries = run_svn_log(svn_url, cur_rev, stop_rev, chunk_length)
+        entries = once_or_more("Fetching SVN log", retry, run_svn_log, svn_url, cur_rev, stop_rev, chunk_length)
         duration = time.time() - start_t
         if not entries:
             if stop_rev == last_rev:

hgsvn/unittests/test_common.py

         f.close()
         common.run_hg(["add", "bar"])
         eq_(False, common.hg_switch_branch("test", "default"))
+
+class TestOnceOrMore(object):
+    def setUp(self):
+        self._counter = 0
+
+    def increment(self, count):
+        self._counter += count
+        return self._counter
+
+    def increment_until_3(self, count):
+        self.increment(count)
+        if self._counter < 3:
+            raise Exception("Counter not high enough yet")
+
+    def test_no_exception(self):
+        foo = common.once_or_more("Foo", False, self.increment, 1)
+        eq_(1, self._counter)
+        eq_(1, foo)
+        foo = common.once_or_more("Foo", True, self.increment, 2)
+        eq_(3, self._counter)
+        eq_(3, foo)
+
+    @raises(Exception)
+    def test_with_exception_no_retry(self):
+        eq_(0, self._counter)
+        common.once_or_more("Foo", False, self.increment_until_3, 1)
+
+    def test_with_exception_retry(self):
+        eq_(0, self._counter)
+        common.once_or_more("Foo", True, self.increment_until_3, 1)
+        eq_(3, self._counter)
+    
+        
+            
+
+
+