1
0
Fork 0
Commit graph

23 commits

Author SHA1 Message Date
Florent Rougon
c72de824d2 terrasync.py: more modular code layout
- New directory scripts/python/TerraSync/terrasync.

- Move scripts/python/terrasync.py to
  scripts/python/TerraSync/terrasync/main.py (main module in the new
  structure).

- Add empty __init__.py file to scripts/python/TerraSync/terrasync/ to
  make this directory a Python package.

- Wrap the main code from previous terrasync.py in a main() function of
  the terrasync.main module. Also move command-line arguments parsing to
  a separate parseCommandLine() function.

- Add an executable script scripts/python/TerraSync/terrasync.py for end
  users, that just calls terrasync.main.main().

For end users, the only difference is that they now have to use
scripts/python/TerraSync/terrasync.py instead of
scripts/python/terrasync.py (which doesn't exist anymore, since all this
lives under the scripts/python/TerraSync directory from now on).

This structure will allow to cleanly split the code into modules and to
add unit tests.
2018-02-07 11:38:41 +01:00
Florent Rougon
eb23f8906d terrasync.py: use os.path.abspath() in TerraSync.setTarget()
Using os.path.abspath() here in TerraSync.setTarget() adds a safety
layer in case the process later calls os.chdir() or similar[1], which
would change the meaning of the "." directory. Also remove the strip()
call which I don't consider useful here, see my message at:

  https://sourceforge.net/p/flightgear/mailman/message/36208140/

[1] Not the case currently, but who knows what will happen in the
    future...
2018-02-03 11:22:56 +01:00
Florent Rougon
77513a2498 terrasync.py: update script header
In particular, terrasync.py appears *not* to require dnspython. :-)
2018-02-03 11:22:56 +01:00
Florent Rougon
8693e442d7 terrasync.py: add options --mode and --report
You may now call terrasync.py with --mode=sync or --mode=check. 'sync'
mode is the default and corresponds to terrasync.py's usual behavior.

In 'check' mode, terrasync.py never writes to disk and aborts at the
first mismatch between local and remote data. The exit status in 'check'
mode is:
  - 0 if the program terminated successfully and no mismatch was found
    between the local and remote repositories;
  - 1 in case an error was encountered;
  - 2 if there was a mismatch between local and remote data.

In 'sync' mode, the exit status is:
  - 0 if the program terminated successfully;
  - 1 in case an error was encountered.

A mismatch in 'check' mode is *not* an error, it is just one of the two
expected results. An error is a worse condition (uncaught exception,
network retrieval aborted after retrying failed, stuff like that).

Additionally, calling terrasync.py with --report causes it to print
lists of:
  - files and dirs that were missing or had mismatching hashes (this is
    okay in 'sync' mode: these things have been "fixed" in the target
    directory before the report was printed);
  - files and dirs that have been found to be orphaned (i.e., found
    under the target directory but not mentioned in the corresponding
    .dirindex file). These are the ones removed in 'sync' mode when
    --remove-orphan is passed.
2018-02-03 11:22:56 +01:00
Florent Rougon
6d323bbbdc terrasync.py: prepare the terrain for --mode and --report
- Add computeHash() utility function that can work with any file-like
  object (e.g., a connected socket).

- Rename hash_of_file() to hashForFile(), and of course implement it
  using our new computeHash().

- Add class HTTPSocketRequest derived from HTTPGetCallback. It allows
  one to process data from the network without storing it to a file (it
  uses the file-like interface provided by http.client.HTTPResponse).

  The callback returns the http.client.HTTPResponse object, which can be
  conveniently used in a 'with' statement.

- Simplify the API of TerraSync.updateDirectory(): its 'dirIndexHash'
  argument must now be a hash (a string); the None object is not allowed
  anymore (with the soon-to-come addition of --mode=check, having to
  deal with this special case in updateDirectory() would make the logic
  too difficult to follow, or we would have to really completely
  separate check-only mode from update mode, which would entail code
  duplication).

  Since TerraSync.updateDirectory() must now always have a hash to work
  with, compute the hash of the root '.dirindex' file from the server in
  TerraSync.start(), using our new HTTPSocketRequest class---which was
  written for this purpose, since that will have to work in check-only
  mode (but not only), where we don't want to write any file to disk.

- TerraSync.updateFile(): correctly handle the case where a directory
  inside the TerraSync repository is (now) a file according to the
  server: the directory must be recursively removed before the file can
  be downloaded in the place formerly occupied by the directory.

- Add stub class Report. Its methods do nothing for now, but are already
  called in a couple of appropriate places. The class will be completed
  in a future commit, of course.
2018-02-03 11:22:56 +01:00
Florent Rougon
af021cc1ef terrasync.py: add function removeDirectoryTree() and exception UserError
The goal of removeDirectoryTree() is to provide a safety net around
recursive directory removal with shutil.rmtree(), in order to prevent
user or bug-caused catastrophic events such as /, /home /home/joeuser or
C:\ being recursively erased.
2018-02-03 11:22:56 +01:00
Florent Rougon
2c6f93aa46 terrasync.py: improve retry logic and error handling
- Add method assembleUrl() to HTTPGetter.

- Raise a NetworkError exception with the particular URL and number of
  retries when it has been exhausted.

- Number of retries is now trivial to expose as a parameter, and set to
  5 in HTTPGetter.

- Sleep for one second between self.httpConnection.close() and
  self.httpConnection.connect() when retrying a failed HTTP request.

- Apply DRY principle.
2018-02-03 11:22:56 +01:00
Florent Rougon
c27ae92c73 terrasync.py: improve error handling
- New generic exception class TerraSyncPyException.

- Add subclass NetworkError of TerraSyncPyException.

- Raise a NetworkError exception when the HTTP return code is not 200.

- hash_of_file() does not silently ignore errors anymore; exceptions
  should be dealt with wherever appropriate by the callers.

  Whenever hash_of_file() returns, its return value is now the SHA-1
  hash of the specified file. This is less error-prone IMHO than
  returning None. Otherwise, calling code could erroneously conclude
  that there is a matching hash when the file to check is actually
  missing. For a concrete example, see the 'dirIndexHash' parameter of
  TerraSync.updateDirectory(), which so far is used precisely with the
  value None to express that "we are just starting the recursion and
  have no hash from the server to compare to".
2018-02-03 11:22:56 +01:00
Florent Rougon
19209a71f0 terrasync.py: improve the HTTPGetter and HTTPGetCallback APIs
When called, the callback passed to HTTPGetter.get() is now explicitly
passed the URL and the http.client.HTTPResponse instance.

Remove the HTTPGetCallback.result attribute (not needed anymore, leaves
more freedom when implementating HTTPGetCallback subclasses...).
2018-02-03 11:22:56 +01:00
Florent Rougon
de4291b851 terrasync.py: make HTTPGetter.get() return the HTTPGetCallback.callback ret value
This way, the caller can get access to interesting things from the
callback, such as the HTTPResponse object (wrapper for the socket).
2018-02-03 11:22:56 +01:00
Florent Rougon
b7fc63d896 terrasync.py: remove methods TerraSync.isReady() and TerraSync.update()
These methods don't work, because HTTPGetter objects have no isReady()
and update() methods either.
2018-02-03 11:22:56 +01:00
Florent Rougon
417d81d4c3 terrasync.py: minor changes
These changes should not alter the behavior of terrasync.py.
2018-02-03 11:22:56 +01:00
Torsten Dreyer
a27ea4dfe6 remove orphan directories with --remove-orphan 2017-09-01 10:33:35 +02:00
Saikrishna Arcot
bb0869599b
Switch to using argparse in terrasync.py, which is actually maintained, and fix a couple of errors. 2016-12-28 08:32:55 -06:00
Saikrishna Arcot
eb4738cb02
Switch to using optparse module, and allow settings bounds from command line. 2016-12-27 22:41:59 -06:00
Saikrishna Arcot
e67ea4e0cb
Add in the ability to download scenery only for a specific section. 2016-12-27 21:17:46 -06:00
Saikrishna Arcot
2c5429c589
Improve error handling.
If the response to the HTTP request isn't 200 (success), then don't save
the response, and don't call the callback.

Additionally, only retry in the case of HTTPException. This allows using
Ctrl-C to work correctly (and easily).
2016-12-27 20:46:59 -06:00
Torsten Dreyer
b9cba13e32 Fix the root cause for terrasync.py timeouts
Thanks to Andre Coetzee for spotting.

Also, don't hardcode port 80, intead use the port given in the url
2016-06-06 12:17:12 +02:00
Torsten Dreyer
a93dd29c85 First attempt to handle the nasty socket timeout
Retry once if a http get fails
2016-05-25 16:19:36 +02:00
Torsten Dreyer
489be2ce16 Add user-agent request header 2016-05-18 15:14:59 +02:00
Torsten Dreyer
6921c98933 Much better terrasync.py
- tortellini instead of spaghetti code (use oop)
- reuse connection
2016-05-18 12:51:29 +02:00
Torsten Dreyer
e2afbb4678 terrasync.py: cleanup and add some more power
- add option --quick
  check sha1sum of .dirindex files and skip directory if hash matches
- add option --remove-orphan
  remove orphan files (files exist locally but not on server)
- be less verbose
- write .dirindex files locally
2016-05-11 23:04:24 +02:00
Torsten Dreyer
0c5e99504d Move terrasync.py to /scripts/python 2016-05-11 14:59:36 +02:00
Renamed from utils/TerraSync/terrasync.py (Browse further)