cedar-backup-svn Mailing List for Cedar Backup
Brought to you by:
pronovic
You can subscribe to this list here.
| 2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(5) |
Dec
(50) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2008 |
Jan
|
Feb
(5) |
Mar
(55) |
Apr
(13) |
May
(6) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(5) |
Nov
(3) |
Dec
(3) |
| 2009 |
Jan
|
Feb
|
Mar
(11) |
Apr
|
May
|
Jun
|
Jul
|
Aug
(7) |
Sep
|
Oct
|
Nov
|
Dec
|
| 2010 |
Jan
(14) |
Feb
(2) |
Mar
|
Apr
|
May
(7) |
Jun
(8) |
Jul
(30) |
Aug
|
Sep
|
Oct
(4) |
Nov
|
Dec
|
| 2011 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(9) |
Nov
|
Dec
|
| 2013 |
Jan
|
Feb
|
Mar
(3) |
Apr
(10) |
May
(6) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2014 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(48) |
Nov
(1) |
Dec
|
| 2015 |
Jan
(5) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(3) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <pro...@us...> - 2015-07-26 08:03:48
|
Revision: 1103
http://sourceforge.net/p/cedar-backup/code/1103
Author: pronovic
Date: 2015-07-26 08:03:46 +0000 (Sun, 26 Jul 2015)
Log Message:
-----------
Final tweaks for BitBucket transition
Modified Paths:
--------------
web/trunk/cedar-backup/config/header.gth
web/trunk/cedar-backup/source/gpl.gtml
web/trunk/cedar-backup/source/index.gtml
web/trunk/cedar-backup/source/terms.gtml
Modified: web/trunk/cedar-backup/config/header.gth
===================================================================
--- web/trunk/cedar-backup/config/header.gth 2015-07-26 07:44:06 UTC (rev 1102)
+++ web/trunk/cedar-backup/config/header.gth 2015-07-26 08:03:46 UTC (rev 1103)
@@ -11,7 +11,7 @@
<meta name="keywords" content="<<PAGE_KEYWORDS>>">
<meta name="description" content="<<PAGE_DESCRIPTION>>">
- <meta http-equiv="refresh" content="15; url=<<BITBUCKET_URL>>" /> <!-- Redirect to the real site -->
+ <meta http-equiv="refresh" content="30; url=<<BITBUCKET_URL>>" /> <!-- Redirect to the real site -->
<link rel="icon" href="/favicon.ico" type="image/ico">
<link rel="shortcut icon" href="/favicon.ico" type="image/ico">
Modified: web/trunk/cedar-backup/source/gpl.gtml
===================================================================
--- web/trunk/cedar-backup/source/gpl.gtml 2015-07-26 07:44:06 UTC (rev 1102)
+++ web/trunk/cedar-backup/source/gpl.gtml 2015-07-26 08:03:46 UTC (rev 1103)
@@ -31,7 +31,7 @@
<p>
Please visit the BitBucket site for <a href="<<BITBUCKET_2_URL>>">Cedar Backup version 2</a>
or <a href="<<BITBUCKET_2_URL>>">Cedar Backup version 3</a> for more information.
-<b>You will be redirected shortly.</b>.
+<b>You will be redirected shortly...</b>
</p>
#include "content_footer.gth"
Modified: web/trunk/cedar-backup/source/index.gtml
===================================================================
--- web/trunk/cedar-backup/source/index.gtml 2015-07-26 07:44:06 UTC (rev 1102)
+++ web/trunk/cedar-backup/source/index.gtml 2015-07-26 08:03:46 UTC (rev 1103)
@@ -31,7 +31,7 @@
<p>
Please visit the BitBucket site for <a href="<<BITBUCKET_2_URL>>">Cedar Backup version 2</a>
or <a href="<<BITBUCKET_2_URL>>">Cedar Backup version 3</a> for more information.
-<b>You will be redirected shortly.</b>.
+<b>You will be redirected shortly...</b>
</p>
#include "content_footer.gth"
Modified: web/trunk/cedar-backup/source/terms.gtml
===================================================================
--- web/trunk/cedar-backup/source/terms.gtml 2015-07-26 07:44:06 UTC (rev 1102)
+++ web/trunk/cedar-backup/source/terms.gtml 2015-07-26 08:03:46 UTC (rev 1103)
@@ -31,7 +31,7 @@
<p>
Please visit the BitBucket site for <a href="<<BITBUCKET_2_URL>>">Cedar Backup version 2</a>
or <a href="<<BITBUCKET_2_URL>>">Cedar Backup version 3</a> for more information.
-<b>You will be redirected shortly.</b>.
+<b>You will be redirected shortly...</b>
</p>
#include "content_footer.gth"
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2015-07-26 07:44:09
|
Revision: 1102
http://sourceforge.net/p/cedar-backup/code/1102
Author: pronovic
Date: 2015-07-26 07:44:06 +0000 (Sun, 26 Jul 2015)
Log Message:
-----------
More BitBucket tweaks
Modified Paths:
--------------
web/trunk/cedar-backup/config/footer.gth
web/trunk/cedar-backup/config/site-wide.gth
web/trunk/cedar-backup/source/index.gtml
Modified: web/trunk/cedar-backup/config/footer.gth
===================================================================
--- web/trunk/cedar-backup/config/footer.gth 2015-07-26 07:42:21 UTC (rev 1101)
+++ web/trunk/cedar-backup/config/footer.gth 2015-07-26 07:44:06 UTC (rev 1102)
@@ -10,8 +10,6 @@
<h3><span>Navigation</span></h3>
<ul>
<li><a href="<<HOME_URL>>" accesskey="h">Cedar Backup <span class="accesskey">H</span>ome</a></li>
- <li><a href="<<V2_MANUAL_URL>>"accesskey="u">Software <span class="accesskey">U</span>ser Manual</a></li>
- <li><a href="<<SF_LATEST_URL>>"accesskey="r">Latest <span class="accesskey">R</span>elease</a></li>
<li><a href="<<SF_PROJECT_URL>>"accesskey="p">SF <span class="accesskey">P</span>roject Page</a></li>
<li><a href="<<SF_DOWNLOADS_URL>>"accesskey="d">SF <span class="accesskey">D</span>ownloads</a></li>
<li><a href="<<SF_LISTS_URL>>"accesskey="l">SF Mailing <span class="accesskey">L</span>ists</a></li>
@@ -33,7 +31,6 @@
<div id="sourceforge">
<h3><span>Project Hosting:</span</h3>
<<SF_LOGO>>
- <<CLOUDBEES_LOGO>>
</div>
</div> <!-- end id="sidebar" -->
Modified: web/trunk/cedar-backup/config/site-wide.gth
===================================================================
--- web/trunk/cedar-backup/config/site-wide.gth 2015-07-26 07:42:21 UTC (rev 1101)
+++ web/trunk/cedar-backup/config/site-wide.gth 2015-07-26 07:44:06 UTC (rev 1102)
@@ -33,6 +33,4 @@
#define DEBIAN_URL http://debian.org/
#define SF_LOGO <a href="http://sourceforge.net"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=210468&type=2" width="125" height="37" border="0" alt="SourceForge.net Logo" /></a>
-#define CLOUDBEES_LOGO <a href="https://cedar-solutions.ci.cloudbees.com/"><img src="http://www.cloudbees.com/sites/default/files/styles/large/public/Button-Powered-by-CB.png" width="130" border="0" alt="Cloudbees Logo" /></a>
-#define DEVATCLOUD_LOGO <a href="https://cedar-solutions.ci.cloudbees.com/"><img src="https://www.cloudbees.com/sites/default/files/styles/large/public/Button-Built-on-CB-1.png" border="0" alt="DEV@cloud Logo" /></a>
Modified: web/trunk/cedar-backup/source/index.gtml
===================================================================
--- web/trunk/cedar-backup/source/index.gtml 2015-07-26 07:42:21 UTC (rev 1101)
+++ web/trunk/cedar-backup/source/index.gtml 2015-07-26 07:44:06 UTC (rev 1102)
@@ -34,16 +34,6 @@
<b>You will be redirected shortly.</b>.
</p>
-<a name="ci"></a>
-<h2>Continuous Integration</h2>
-
-<p>
-Continuous integration via <a href="https://cedar-solutions.ci.cloudbees.com">Jenkins</a>
-is graciously hosted by CloudBees using their Dev@cloud solution.
-</p>
-
-<<DEVATCLOUD_LOGO>>
-
#include "content_footer.gth"
#include "footer.gth"
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2015-07-26 07:42:24
|
Revision: 1101
http://sourceforge.net/p/cedar-backup/code/1101
Author: pronovic
Date: 2015-07-26 07:42:21 +0000 (Sun, 26 Jul 2015)
Log Message:
-----------
Adjust site to account for move to BitBucket
Modified Paths:
--------------
web/trunk/cedar-backup/config/header.gth
web/trunk/cedar-backup/config/site-wide.gth
web/trunk/cedar-backup/source/gpl.gtml
web/trunk/cedar-backup/source/index.gtml
web/trunk/cedar-backup/source/terms.gtml
Modified: web/trunk/cedar-backup/config/header.gth
===================================================================
--- web/trunk/cedar-backup/config/header.gth 2015-01-05 20:52:33 UTC (rev 1100)
+++ web/trunk/cedar-backup/config/header.gth 2015-07-26 07:42:21 UTC (rev 1101)
@@ -10,8 +10,9 @@
<meta name="author" content="<<SITE_OWNER>>"/>
<meta name="keywords" content="<<PAGE_KEYWORDS>>">
<meta name="description" content="<<PAGE_DESCRIPTION>>">
- <meta name="google-site-verification" content="NodwmqotlVxAAhJ15aV7eK7KcFlxqEWlN8CVwsTiFZs" />
+ <meta http-equiv="refresh" content="15; url=<<BITBUCKET_URL>>" /> <!-- Redirect to the real site -->
+
<link rel="icon" href="/favicon.ico" type="image/ico">
<link rel="shortcut icon" href="/favicon.ico" type="image/ico">
Modified: web/trunk/cedar-backup/config/site-wide.gth
===================================================================
--- web/trunk/cedar-backup/config/site-wide.gth 2015-01-05 20:52:33 UTC (rev 1100)
+++ web/trunk/cedar-backup/config/site-wide.gth 2015-07-26 07:42:21 UTC (rev 1101)
@@ -2,7 +2,7 @@
#define CONTACT_EMAIL pro...@ie...
#define SUPPORT_EMAIL su...@ce...
#define WEBMASTER_EMAIL pro...@ie...
-#define COPYRIGHT_DATE 2007,2013
+#define COPYRIGHT_DATE 2007,2013,2015
#define SITE_NAME Cedar Backup
@@ -24,8 +24,9 @@
#define SF_CODE_URL <<SF_URL>>/p/cedar-backup/code/HEAD/tree/cedar-backup2/
#define SF_SVN_BROWSE_URL http://cedar-backup.svn.sourceforge.net/viewvc/cedar-backup/
-#define V2_DOC_DIR_URL <<DOC_DIR_URL>>/cedar-backup2
-#define V2_MANUAL_URL <<V2_DOC_DIR_URL>>/manual/index.html
+#define BITBUCKET_URL https://bitbucket.org/cedarsolutions
+#define BITBUCKET_2_URL https://bitbucket.org/cedarsolutions/cedar-backup2
+#define BITBUCKET_3_URL https://bitbucket.org/cedarsolutions/cedar-backup3
#define CEDAR_URL http://software.cedar-solutions.com/
#define CEDAR_DEBIAN_URL <<CEDAR_URL>>/debian.html
Modified: web/trunk/cedar-backup/source/gpl.gtml
===================================================================
--- web/trunk/cedar-backup/source/gpl.gtml 2015-01-05 20:52:33 UTC (rev 1100)
+++ web/trunk/cedar-backup/source/gpl.gtml 2015-07-26 07:42:21 UTC (rev 1101)
@@ -11,320 +11,28 @@
#include "content_header.gth"
-<!-- <P> vs <p> style, etc. varies in here because I didn't code
- this version of the license. Sorry. -->
+<h2>Cedar Backup</h2>
-<P>
-<H1><A NAME="SEC1">GNU GENERAL PUBLIC LICENSE</A></H1>
-Version 2, June 1991
-<P>
-<PRE>
-Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-675 Mass Ave, Cambridge, MA 02139, USA
+<p>
+Cedar Backup is a software package designed to manage system backups for a pool
+of local and remote machines. Cedar Backup understands how to back up
+filesystem data as well as MySQL and PostgreSQL databases and Subversion
+repositories. It can also be easily extended to support other kinds of data
+sources.
+</p>
-Everyone is permitted to copy and distribute verbatim copies
-of this license document, but changing it is not allowed.
-</PRE>
-<P>
-<H2><A NAME="SEC2">Preamble</A></H2>
-<P>
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-<P>
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-<P>
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-<P>
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-<P>
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-<P>
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-<P>
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-<P>
- The precise terms and conditions for copying, distribution and
-modification follow.
-<P>
-<H2><A NAME="SEC3">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</A></H2>
-<P>
-<OL>
-<LI>
-This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-<P>
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-<P>
-<LI>
-You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-<P>
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-<P>
-<LI>
-You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-<P>
-<OL>
-<LI>
-You must cause the modified files to carry prominent notices
-stating that you changed the files and the date of any change.
-<P>
-<LI>
-You must cause any work that you distribute or publish, that in
-whole or in part contains or is derived from the Program or any
-part thereof, to be licensed as a whole at no charge to all third
-parties under the terms of this License.
-<P>
-<LI>
-If the modified program normally reads commands interactively
-when run, you must cause it, when started running for such
-interactive use in the most ordinary way, to print or display an
-announcement including an appropriate copyright notice and a
-notice that there is no warranty (or else, saying that you provide
-a warranty) and that users may redistribute the program under
-these conditions, and telling the user how to view a copy of this
-License. (Exception: if the Program itself is interactive but
-does not normally print such an announcement, your work based on
-the Program is not required to print an announcement.)
-</OL>
-<P>
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-<P>
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-<P>
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-<P>
-<LI>
-You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-<P>
-<OL>
-<LI>
-Accompany it with the complete corresponding machine-readable
-source code, which must be distributed under the terms of Sections
-1 and 2 above on a medium customarily used for software interchange; or,
-<P>
-<LI>
-Accompany it with a written offer, valid for at least three
-years, to give any third party, for a charge no more than your
-cost of physically performing source distribution, a complete
-machine-readable copy of the corresponding source code, to be
-distributed under the terms of Sections 1 and 2 above on a medium
-customarily used for software interchange; or,
-<P>
-<LI>
-Accompany it with the information you received as to the offer
-to distribute corresponding source code. (This alternative is
-allowed only for noncommercial distribution and only if you
-received the program in object code or executable form with such
-an offer, in accord with Subsection b above.)
-</OL>
-<P>
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-<P>
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-<P>
-<LI>
-You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-<P>
-<LI>
-You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-<P>
-<LI>
-Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-<P>
-<LI>
-If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-<P>
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-<P>
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-<P>
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-<P>
-<LI>
-If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-<P>
-<LI>
-The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-<P>
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-<P>
-<LI>
-If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-<P>
-<H2>NO WARRANTY</H2>
-<P>
-<LI>
-BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-<P>
-<LI>
-IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-</OL>
-<P>
-<H2>END OF TERMS AND CONDITIONS</H2>
-<P>
-<BR>
+<p>
+As of mid-2015, development on Cedar Backup has moved from SourceForge to
+BitBucket, and revision control has changed from Subversion to Mercurial.
+Historical releases and the original Subversion repository will stay here
+at SourceForge indefinitely.
+</p>
+<p>
+Please visit the BitBucket site for <a href="<<BITBUCKET_2_URL>>">Cedar Backup version 2</a>
+or <a href="<<BITBUCKET_2_URL>>">Cedar Backup version 3</a> for more information.
+<b>You will be redirected shortly.</b>.
+</p>
+
#include "content_footer.gth"
-
#include "footer.gth"
Modified: web/trunk/cedar-backup/source/index.gtml
===================================================================
--- web/trunk/cedar-backup/source/index.gtml 2015-01-05 20:52:33 UTC (rev 1100)
+++ web/trunk/cedar-backup/source/index.gtml 2015-07-26 07:42:21 UTC (rev 1101)
@@ -11,8 +11,7 @@
#include "content_header.gth"
-<a name="whatis"></a>
-<h2>What is Cedar Backup?</h2>
+<h2>Cedar Backup</h2>
<p>
Cedar Backup is a software package designed to manage system backups for a pool
@@ -23,154 +22,18 @@
</p>
<p>
-Cedar Backup is focused around weekly backups to a single CD or DVD disc, with
-the expectation that the disc will be changed or overwritten at the beginning
-of each week. If your hardware is new enough (and almost all hardware is
-today), Cedar Backup can write multisession discs, allowing you to add
-incremental data to a disc on a daily basis.
+As of mid-2015, development on Cedar Backup has moved from SourceForge to
+BitBucket, and revision control has changed from Subversion to Mercurial.
+Historical releases and the original Subversion repository will stay here
+at SourceForge indefinitely.
</p>
<p>
-Alternately, Cedar Backup can write your backups to the Amazon S3 cloud
-rather than relying on physical media.
+Please visit the BitBucket site for <a href="<<BITBUCKET_2_URL>>">Cedar Backup version 2</a>
+or <a href="<<BITBUCKET_2_URL>>">Cedar Backup version 3</a> for more information.
+<b>You will be redirected shortly.</b>.
</p>
-<p>
-Besides offering command-line utilities to manage the backup process, Cedar
-Backup provides a well-organized library of backup-related functionality,
-written in the Python programming language.
-</p>
-
-<p>
-There are many different backup software implementations out there in the free
-software and open source world. Cedar Backup aims to fill a niche: it aims to
-be a good fit for people who need to back up a limited amount of important data
-to CD or DVD on a regular basis. Cedar Backup isn't for you if you want to back
-up your MP3 collection every night, or if you want to back up a few hundred
-machines. However, if you administer a small set of machines and you want to
-run daily incremental backups for things like system configuration, current
-email, small web sites, a CVS or Subversion repository, or a small MySQL
-database, then Cedar Backup is probably worth your time.
-</p>
-
-<p>
-Cedar Backup has been developed on a
-<a href="http://www.debian.org/">Debian GNU/Linux</a>
-system and is primarily supported on Debian and other Linux systems.
-However, since it is written in portable
-<a href="http://www.python.org">Python</a>, it should run without problems on
-just about any UNIX-like operating system. In particular, Cedar Backup has
-users running Debian, RedHat and SuSE Linux systems as well as FreeBSD and Mac
-OS X systems.
-</p>
-
-<h2>Library Code</h2>
-
-<p>
-The version 2 release of Cedar Backup has been designed as both an application and a
-library of backup-related functionality. The <tt>CedarBackup2</tt> Python
-package contains a variety of useful backup-related classes and functions. For
-instance: the <tt>IsoImage</tt> class represents an ISO CD image;
-the <tt>CdWriter</tt> class represents a CD-R/CD-RW writer device; and the
-<tt>FilesystemList</tt> class represents a list of files and directories on a
-filesystem. For more information, see the
-<a href="<<V2_DOC_DIR_URL>>/interface/index.html">public interface documentation</a>,
-generated from the source code using <a href="http://epydoc.sourceforge.net">Epydoc</a>.
-</p>
-
-<h2>Documentation</h2>
-
-<p>
-The Cedar Backup Software Manual documents the process of setting up and using
-Cedar Backup. In the manual, you can find information about how Cedar Backup
-works, how to install and configure it, how to schedule backups, how to restore
-data, and how to get support.
-</p>
-
-<p>
-The following versions of the manual are available:
-</p>
-
-<ul>
- <li><a href="<<V2_DOC_DIR_URL>>/manual/manual.html">Single-page HTML</a></li>
- <li><a href="<<V2_DOC_DIR_URL>>/manual/index.html">Multiple-page HTML</a></li>
- <li><a href="<<V2_DOC_DIR_URL>>/manual/manual.txt">Plaintext</a></li>
-</ul>
-
-<p>
-Most users will want to look at the multiple-page HTML version.
-</p>
-
-<a name="packages"></a>
-<h2>Package Distributions</h2>
-
-<p>
-The current production release of Cedar Backup is version 2 (project
-"cedar-backup2"). The old version 1 release ("cedar-backup") is still
-available for historical purposes, but is unsupported.
-</p>
-
-<p>
-Cedar Backup is primarily distributed as a Python source package.
-You can download the latest release from the
-SourceForge <a href="<<SF_DOWNLOADS_URL>>">download page</a>.
-</p>
-
-<p>
-Any recent Debian-based distribution (either Debian itself or
-a derivative such as Ubuntu) includes official Cedar Backup packages,
-called <tt>cedar-backup2</tt> and <tt>cedar-backup2-doc</tt>.
-</p>
-
-<p>
-Debian users who want to always run the latest release of Cedar Backup, rather than
-the version included with their distribution, can use the Cedar Solutions APT
-source. See the Cedar Solutions <a href="<<CEDAR_DEBIAN_URL>>">Debian page</a>
-for more information.
-</p>
-
-<a name="support"></a>
-<h2>Support</h2>
-
-<p>
-Support is primarily managed through the SourceForge
-<a href="<<SF_LISTS_URL>>">mailing lists</a>.
-If you would prefer, you can write the Cedar Solutions
-<a href="mail:<<SUPPORT_EMAIL>>">support email address</a> instead.
-</p>
-
-<p>
-If you think you have found a bug or you would like to request an enhancement,
-file a ticket with SourceForge <a href="<<SF_BTS_URL>>">tracker</a> or submit a
-patch, or email <a href="mailto:<<CONTACT_EMAIL>>">Ken</a> directly.
-</p>
-
-<a name="contributing"></a>
-<h2>Contributing Improvements</h2>
-
-<p>
-Users are welcome to contribute improvements to Cedar Backup. In the past,
-users have helped out by reporting unit test failures, making suggestions,
-requesting enhancements, updating documentation, submitting patches, and
-beta-testing entire releases or individual bug fixes. As a result, Cedar
-Backup has evolved into a much more flexible platform than it would otherwise
-have been. If you are interested in contributing, drop an email off to the
-Cedar Solutions
-<a href="mailto:<<SUPPORT_EMAIL>>">support email address</a>
-or to <a href="mailto:<<CONTACT_EMAIL>>">Ken</a> directly.
-</p>
-
-<a name="sourcecode"></a>
-<h2>Source Code</h2>
-
-<p>
-Cedar Backup is hosted at <a href="<<SF_URL>>">SourceForge</a>. Anonymous
-read-only access to the Subversion source code repository is available as
-described on the SourceForge <a href="<<SF_CODE_URL>>">code page</a>. You can
-also <a href="<<SF_SVN_BROWSE_URL>>">browse</a> the Subversion repository
-online.
-</p>
-
<a name="ci"></a>
<h2>Continuous Integration</h2>
Modified: web/trunk/cedar-backup/source/terms.gtml
===================================================================
--- web/trunk/cedar-backup/source/terms.gtml 2015-01-05 20:52:33 UTC (rev 1100)
+++ web/trunk/cedar-backup/source/terms.gtml 2015-07-26 07:42:21 UTC (rev 1101)
@@ -11,26 +11,28 @@
#include "content_header.gth"
-<h2>Terms of Use</h2>
+<h2>Cedar Backup</h2>
<p>
-All pages in this web site, including this one, contain a disclaimer
-embedded as a comment. This disclaimer has been reproduced below.
-If you have questions with regard to the allowed use of site content,
-first read the embedded disclaimer on the top of the page in question
-(which may differ slightly from the disclaimer reproduced below),
-and the contact the <a href="mailto:<<WEBMASTER_EMAIL>>">Webmaster</a>
-if you still have questions.
+Cedar Backup is a software package designed to manage system backups for a pool
+of local and remote machines. Cedar Backup understands how to back up
+filesystem data as well as MySQL and PostgreSQL databases and Subversion
+repositories. It can also be easily extended to support other kinds of data
+sources.
</p>
-<pre>
-#include "copyright.gth"
-</pre>
+<p>
+As of mid-2015, development on Cedar Backup has moved from SourceForge to
+BitBucket, and revision control has changed from Subversion to Mercurial.
+Historical releases and the original Subversion repository will stay here
+at SourceForge indefinitely.
+</p>
<p>
-You can read the specification for GPLv2 <a href="<<GPL_URL>>">here</a>.
+Please visit the BitBucket site for <a href="<<BITBUCKET_2_URL>>">Cedar Backup version 2</a>
+or <a href="<<BITBUCKET_2_URL>>">Cedar Backup version 3</a> for more information.
+<b>You will be redirected shortly.</b>.
</p>
#include "content_footer.gth"
#include "footer.gth"
-
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2015-01-05 20:52:34
|
Revision: 1100
http://sourceforge.net/p/cedar-backup/code/1100
Author: pronovic
Date: 2015-01-05 20:52:33 +0000 (Mon, 05 Jan 2015)
Log Message:
-----------
Tagging the 2.24.2 release of Cedar Backup.
Added Paths:
-----------
cedar-backup2/tags/CEDAR_BACKUP2_V2.24.2/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2015-01-05 20:49:25
|
Revision: 1099
http://sourceforge.net/p/cedar-backup/code/1099
Author: pronovic
Date: 2015-01-05 20:49:18 +0000 (Mon, 05 Jan 2015)
Log Message:
-----------
Release 2.24.2
Modified Paths:
--------------
cedar-backup2/trunk/CedarBackup2/release.py
cedar-backup2/trunk/Changelog
Modified: cedar-backup2/trunk/CedarBackup2/release.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/release.py 2015-01-05 20:48:57 UTC (rev 1098)
+++ cedar-backup2/trunk/CedarBackup2/release.py 2015-01-05 20:49:18 UTC (rev 1099)
@@ -33,8 +33,8 @@
AUTHOR = "Kenneth J. Pronovici"
EMAIL = "pro...@ie..."
-COPYRIGHT = "2004-2011,2013,2014"
-VERSION = "2.24.1"
-DATE = "07 Oct 2014"
+COPYRIGHT = "2004-2011,2013-2015"
+VERSION = "2.24.2"
+DATE = "05 Jan 2015"
URL = "http://cedar-backup.sourceforge.net/"
Modified: cedar-backup2/trunk/Changelog
===================================================================
--- cedar-backup2/trunk/Changelog 2015-01-05 20:48:57 UTC (rev 1098)
+++ cedar-backup2/trunk/Changelog 2015-01-05 20:49:18 UTC (rev 1099)
@@ -1,4 +1,4 @@
-Version 2.24.2 unreleased
+Version 2.24.2 05 Jan 2015
* Add optional size-limit configuration for amazons3 extension.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2015-01-05 20:48:59
|
Revision: 1098
http://sourceforge.net/p/cedar-backup/code/1098
Author: pronovic
Date: 2015-01-05 20:48:57 +0000 (Mon, 05 Jan 2015)
Log Message:
-----------
Update procedure
Modified Paths:
--------------
cedar-backup2/trunk/doc/procedure.txt
Modified: cedar-backup2/trunk/doc/procedure.txt
===================================================================
--- cedar-backup2/trunk/doc/procedure.txt 2015-01-05 20:43:36 UTC (rev 1097)
+++ cedar-backup2/trunk/doc/procedure.txt 2015-01-05 20:48:57 UTC (rev 1098)
@@ -3,6 +3,7 @@
- Make final update to Changelog
- Update CedarBackup2/release.py
+- Check in changes
- Run unit tests one last time (make test)
- Run pychecker tests one last time (make check or make allcheck)
- Build the source distributions (make distrib)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2015-01-05 20:43:39
|
Revision: 1097
http://sourceforge.net/p/cedar-backup/code/1097
Author: pronovic
Date: 2015-01-05 20:43:36 +0000 (Mon, 05 Jan 2015)
Log Message:
-----------
Test amazons3 changes
Modified Paths:
--------------
cedar-backup2/trunk/CedarBackup2/extend/amazons3.py
Modified: cedar-backup2/trunk/CedarBackup2/extend/amazons3.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/extend/amazons3.py 2015-01-05 20:24:25 UTC (rev 1096)
+++ cedar-backup2/trunk/CedarBackup2/extend/amazons3.py 2015-01-05 20:43:36 UTC (rev 1097)
@@ -645,12 +645,14 @@
logger.debug("Amazon S3 size limit is: %d bytes" % limit)
contents = BackupFileList()
for stagingDir in stagingDirs:
- contents.addDir(stagingDir)
+ contents.addDirContents(stagingDir)
total = contents.totalSize()
logger.debug("Amazon S3 backup size is is: %d bytes" % total)
if total > limit:
- logger.debug("Amazon S3 size limit exceeded: %.0f bytes > %d bytes" % (total, limit))
+ logger.error("Amazon S3 size limit exceeded: %.0f bytes > %d bytes" % (total, limit))
raise ValueError("Amazon S3 size limit exceeded: %.0f bytes > %d bytes" % (total, limit))
+ else:
+ logger.info("Total size does not exceed Amazon S3 size limit, so backup can continue.")
##############################
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2015-01-05 20:24:34
|
Revision: 1096
http://sourceforge.net/p/cedar-backup/code/1096
Author: pronovic
Date: 2015-01-05 20:24:25 +0000 (Mon, 05 Jan 2015)
Log Message:
-----------
Add optional size-limit configuration for amazons3 extension.
Modified Paths:
--------------
cedar-backup2/trunk/CREDITS
cedar-backup2/trunk/CedarBackup2/extend/amazons3.py
cedar-backup2/trunk/CedarBackup2/xmlutil.py
cedar-backup2/trunk/Changelog
cedar-backup2/trunk/manual/src/extensions.xml
cedar-backup2/trunk/testcase/amazons3tests.py
cedar-backup2/trunk/testcase/data/amazons3.conf.2
Modified: cedar-backup2/trunk/CREDITS
===================================================================
--- cedar-backup2/trunk/CREDITS 2014-11-17 21:51:30 UTC (rev 1095)
+++ cedar-backup2/trunk/CREDITS 2015-01-05 20:24:25 UTC (rev 1096)
@@ -23,7 +23,7 @@
software, as indicated in the source code itself.
Unless otherwise indicated, all Cedar Backup source code is Copyright
-(c) 2004-2011,2013,2014 Kenneth J. Pronovici and is released under the GNU
+(c) 2004-2011,2013-2015 Kenneth J. Pronovici and is released under the GNU
General Public License, version 2. The contents of the GNU General Public
License can be found in the LICENSE file, or can be downloaded from
http://www.gnu.org/.
Modified: cedar-backup2/trunk/CedarBackup2/extend/amazons3.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/extend/amazons3.py 2014-11-17 21:51:30 UTC (rev 1095)
+++ cedar-backup2/trunk/CedarBackup2/extend/amazons3.py 2015-01-05 20:24:25 UTC (rev 1096)
@@ -8,7 +8,7 @@
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
-# Copyright (c) 2014 Kenneth J. Pronovici.
+# Copyright (c) 2014-2015 Kenneth J. Pronovici.
# All rights reserved.
#
# This program is free software; you can redistribute it and/or
@@ -94,10 +94,10 @@
import shutil
# Cedar Backup modules
-from CedarBackup2.filesystem import FilesystemList
-from CedarBackup2.util import resolveCommand, executeCommand, isRunningAsRoot, changeOwnership
-from CedarBackup2.xmlutil import createInputDom, addContainerNode, addBooleanNode, addStringNode
-from CedarBackup2.xmlutil import readFirstChild, readString, readBoolean
+from CedarBackup2.filesystem import FilesystemList, BackupFileList
+from CedarBackup2.util import resolveCommand, executeCommand, isRunningAsRoot, changeOwnership, isStartOfWeek
+from CedarBackup2.xmlutil import createInputDom, addContainerNode, addBooleanNode, addStringNode, addLongNode
+from CedarBackup2.xmlutil import readFirstChild, readString, readBoolean, readLong
from CedarBackup2.actions.util import writeIndicatorFile
from CedarBackup2.actions.constants import DIR_TIME_FORMAT, STAGE_INDICATOR
@@ -130,32 +130,42 @@
- The s3Bucket value must be a non-empty string
- The encryptCommand value, if set, must be a non-empty string
+ - The full backup size limit, if set, must be a number of bytes >= 0
+ - The incremental backup size limit, if set, must be a number of bytes >= 0
@sort: __init__, __repr__, __str__, __cmp__, warnMidnite, s3Bucket
"""
- def __init__(self, warnMidnite=None, s3Bucket=None, encryptCommand=None):
+ def __init__(self, warnMidnite=None, s3Bucket=None, encryptCommand=None,
+ fullBackupSizeLimit=None, incrementalBackupSizeLimit=None):
"""
Constructor for the C{AmazonS3Config} class.
@param warnMidnite: Whether to generate warnings for crossing midnite.
@param s3Bucket: Name of the Amazon S3 bucket in which to store the data
@param encryptCommand: Command used to encrypt backup data before upload to S3
+ @param fullBackupSizeLimit: Maximum size of a full backup, in bytes
+ @param incrementalBackupSizeLimit: Maximum size of an incremental backup, in bytes
@raise ValueError: If one of the values is invalid.
"""
self._warnMidnite = None
self._s3Bucket = None
self._encryptCommand = None
+ self._fullBackupSizeLimit = None
+ self._incrementalBackupSizeLimit = None
self.warnMidnite = warnMidnite
self.s3Bucket = s3Bucket
self.encryptCommand = encryptCommand
+ self.fullBackupSizeLimit = fullBackupSizeLimit
+ self.incrementalBackupSizeLimit = incrementalBackupSizeLimit
def __repr__(self):
"""
Official string representation for class instance.
"""
- return "AmazonS3Config(%s, %s, %s)" % (self.warnMidnite, self.s3Bucket, self.encryptCommand)
+ return "AmazonS3Config(%s, %s, %s, %s, %s)" % (self.warnMidnite, self.s3Bucket, self.encryptCommand,
+ self.fullBackupSizeLimit, self.incrementalBackupSizeLimit)
def __str__(self):
"""
@@ -186,6 +196,16 @@
return -1
else:
return 1
+ if self.fullBackupSizeLimit != other.fullBackupSizeLimit:
+ if self.fullBackupSizeLimit < other.fullBackupSizeLimit:
+ return -1
+ else:
+ return 1
+ if self.incrementalBackupSizeLimit != other.incrementalBackupSizeLimit:
+ if self.incrementalBackupSizeLimit < other.incrementalBackupSizeLimit:
+ return -1
+ else:
+ return 1
return 0
def _setWarnMidnite(self, value):
@@ -234,9 +254,59 @@
"""
return self._encryptCommand
+ def _setFullBackupSizeLimit(self, value):
+ """
+ Property target used to set the full backup size limit.
+ The value must be an integer >= 0.
+ @raise ValueError: If the value is not valid.
+ """
+ if value is None:
+ self._fullBackupSizeLimit = None
+ else:
+ try:
+ value = int(value)
+ except TypeError:
+ raise ValueError("Full backup size limit must be an integer >= 0.")
+ if value < 0:
+ raise ValueError("Full backup size limit must be an integer >= 0.")
+ self._fullBackupSizeLimit = value
+
+ def _getFullBackupSizeLimit(self):
+ """
+ Property target used to get the full backup size limit.
+ """
+ return self._fullBackupSizeLimit
+
+ def _setIncrementalBackupSizeLimit(self, value):
+ """
+ Property target used to set the incremental backup size limit.
+ The value must be an integer >= 0.
+ @raise ValueError: If the value is not valid.
+ """
+ if value is None:
+ self._incrementalBackupSizeLimit = None
+ else:
+ try:
+ value = int(value)
+ except TypeError:
+ raise ValueError("Incremental backup size limit must be an integer >= 0.")
+ if value < 0:
+ raise ValueError("Incremental backup size limit must be an integer >= 0.")
+ self._incrementalBackupSizeLimit = value
+
+ def _getIncrementalBackupSizeLimit(self):
+ """
+ Property target used to get the incremental backup size limit.
+ """
+ return self._incrementalBackupSizeLimit
+
warnMidnite = property(_getWarnMidnite, _setWarnMidnite, None, "Whether to generate warnings for crossing midnite.")
s3Bucket = property(_getS3Bucket, _setS3Bucket, None, doc="Amazon S3 Bucket in which to store data")
encryptCommand = property(_getEncryptCommand, _setEncryptCommand, None, doc="Command used to encrypt data before upload to S3")
+ fullBackupSizeLimit = property(_getFullBackupSizeLimit, _setFullBackupSizeLimit, None,
+ doc="Maximum size of a full backup, in bytes")
+ incrementalBackupSizeLimit = property(_getIncrementalBackupSizeLimit, _setIncrementalBackupSizeLimit, None,
+ doc="Maximum size of an incremental backup, in bytes")
########################################################################
@@ -379,9 +449,11 @@
We add the following fields to the document::
- warnMidnite //cb_config/amazons3/warn_midnite
- s3Bucket //cb_config/amazons3/s3_bucket
- encryptCommand //cb_config/amazons3/encrypt
+ warnMidnite //cb_config/amazons3/warn_midnite
+ s3Bucket //cb_config/amazons3/s3_bucket
+ encryptCommand //cb_config/amazons3/encrypt
+ fullBackupSizeLimit //cb_config/amazons3/full_size_limit
+ incrementalBackupSizeLimit //cb_config/amazons3/incr_size_limit
@param xmlDom: DOM tree as from C{impl.createDocument()}.
@param parentNode: Parent that the section should be appended to.
@@ -391,6 +463,8 @@
addBooleanNode(xmlDom, sectionNode, "warn_midnite", self.amazons3.warnMidnite)
addStringNode(xmlDom, sectionNode, "s3_bucket", self.amazons3.s3Bucket)
addStringNode(xmlDom, sectionNode, "encrypt", self.amazons3.encryptCommand)
+ addLongNode(xmlDom, sectionNode, "full_size_limit", self.amazons3.fullBackupSizeLimit)
+ addLongNode(xmlDom, sectionNode, "incr_size_limit", self.amazons3.incrementalBackupSizeLimit)
def _parseXmlData(self, xmlData):
"""
@@ -414,9 +488,11 @@
We read the following individual fields::
- warnMidnite //cb_config/amazons3/warn_midnite
- s3Bucket //cb_config/amazons3/s3_bucket
- encryptCommand //cb_config/amazons3/encrypt
+ warnMidnite //cb_config/amazons3/warn_midnite
+ s3Bucket //cb_config/amazons3/s3_bucket
+ encryptCommand //cb_config/amazons3/encrypt
+ fullBackupSizeLimit //cb_config/amazons3/full_size_limit
+ incrementalBackupSizeLimit //cb_config/amazons3/incr_size_limit
@param parent: Parent node to search beneath.
@@ -430,6 +506,8 @@
amazons3.warnMidnite = readBoolean(section, "warn_midnite")
amazons3.s3Bucket = readString(section, "s3_bucket")
amazons3.encryptCommand = readString(section, "encrypt")
+ amazons3.fullBackupSizeLimit = readLong(section, "full_size_limit")
+ amazons3.incrementalBackupSizeLimit = readLong(section, "incr_size_limit")
return amazons3
@@ -468,6 +546,7 @@
raise ValueError("Cedar Backup configuration is not properly filled in.")
local = LocalConfig(xmlPath=configPath)
stagingDirs = _findCorrectDailyDir(options, config, local)
+ _applySizeLimits(options, config, local, stagingDirs)
_writeToAmazonS3(config, local, stagingDirs)
_writeStoreIndicator(config, stagingDirs)
logger.info("Executed the amazons3 extended action successfully.")
@@ -534,6 +613,47 @@
##############################
+# _applySizeLimits() function
+##############################
+
+def _applySizeLimits(options, config, local, stagingDirs):
+ """
+ Apply size limits, throwing an exception if any limits are exceeded.
+
+ Size limits are optional. If a limit is set to None, it does not apply.
+ The full size limit applies if the full option is set or if today is the
+ start of the week. The incremental size limit applies otherwise. Limits
+ are applied to the total size of all the relevant staging directories.
+
+ @param options: Options object.
+ @param config: Config object.
+ @param local: Local config object.
+ @param stagingDirs: Dictionary mapping directory path to date suffix.
+
+ @raise ValueError: Under many generic error conditions
+ @raise ValueError: If a size limit has been exceeded
+ """
+ if options.full or isStartOfWeek(config.options.startingDay):
+ logger.debug("Using Amazon S3 size limit for full backups.")
+ limit = local.amazons3.fullBackupSizeLimit
+ else:
+ logger.debug("Using Amazon S3 size limit for incremental backups.")
+ limit = local.amazons3.incrementalBackupSizeLimit
+ if limit is None:
+ logger.debug("No Amazon S3 size limit will be applied.")
+ else:
+ logger.debug("Amazon S3 size limit is: %d bytes" % limit)
+ contents = BackupFileList()
+ for stagingDir in stagingDirs:
+ contents.addDir(stagingDir)
+ total = contents.totalSize()
+ logger.debug("Amazon S3 backup size is is: %d bytes" % total)
+ if total > limit:
+ logger.debug("Amazon S3 size limit exceeded: %.0f bytes > %d bytes" % (total, limit))
+ raise ValueError("Amazon S3 size limit exceeded: %.0f bytes > %d bytes" % (total, limit))
+
+
+##############################
# _writeToAmazonS3() function
##############################
Modified: cedar-backup2/trunk/CedarBackup2/xmlutil.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/xmlutil.py 2014-11-17 21:51:30 UTC (rev 1095)
+++ cedar-backup2/trunk/CedarBackup2/xmlutil.py 2015-01-05 20:24:25 UTC (rev 1096)
@@ -246,6 +246,26 @@
else:
return int(result)
+def readLong(parent, name):
+ """
+ Returns long integer contents of the first child with a given name immediately
+ beneath the parent.
+
+ By "immediately beneath" the parent, we mean from among nodes that are
+ direct children of the passed-in parent node.
+
+ @param parent: Parent node to search beneath.
+ @param name: Name of node to search for.
+
+ @return: Long integer contents of node or C{None} if no matching nodes are found.
+ @raise ValueError: If the string at the location can't be converted to an integer.
+ """
+ result = readString(parent, name)
+ if result is None:
+ return None
+ else:
+ return long(result)
+
def readFloat(parent, name):
"""
Returns float contents of the first child with a given name immediately
@@ -353,8 +373,30 @@
if nodeValue is None:
return addStringNode(xmlDom, parentNode, nodeName, None)
else:
- return addStringNode(xmlDom, parentNode, nodeName, "%d" % nodeValue)
+ return addStringNode(xmlDom, parentNode, nodeName, "%d" % nodeValue) # %d works for both int and long
+def addLongNode(xmlDom, parentNode, nodeName, nodeValue):
+ """
+ Adds a text node as the next child of a parent, to contain a long integer.
+
+ If the C{nodeValue} is None, then the node will be created, but will be
+ empty (i.e. will contain no text node child).
+
+ The integer will be converted to a string using "%d". The result will be
+ added to the document via L{addStringNode}.
+
+ @param xmlDom: DOM tree as from C{impl.createDocument()}.
+ @param parentNode: Parent node to create child for.
+ @param nodeName: Name of the new container node.
+ @param nodeValue: The value to put into the node.
+
+ @return: Reference to the newly-created node.
+ """
+ if nodeValue is None:
+ return addStringNode(xmlDom, parentNode, nodeName, None)
+ else:
+ return addStringNode(xmlDom, parentNode, nodeName, "%d" % nodeValue) # %d works for both int and long
+
def addBooleanNode(xmlDom, parentNode, nodeName, nodeValue):
"""
Adds a text node as the next child of a parent, to contain a boolean.
Modified: cedar-backup2/trunk/Changelog
===================================================================
--- cedar-backup2/trunk/Changelog 2014-11-17 21:51:30 UTC (rev 1095)
+++ cedar-backup2/trunk/Changelog 2015-01-05 20:24:25 UTC (rev 1096)
@@ -1,3 +1,7 @@
+Version 2.24.2 unreleased
+
+ * Add optional size-limit configuration for amazons3 extension.
+
Version 2.24.1 07 Oct 2014
* Implement a new tool called cback-amazons3-sync.
Modified: cedar-backup2/trunk/manual/src/extensions.xml
===================================================================
--- cedar-backup2/trunk/manual/src/extensions.xml 2014-11-17 21:51:30 UTC (rev 1095)
+++ cedar-backup2/trunk/manual/src/extensions.xml 2015-01-05 20:24:25 UTC (rev 1096)
@@ -115,11 +115,28 @@
switches over to the configured backup user to run the
<command>aws</command> program. So, make sure you configure the AWS
CLI tools as the backup user and not root. (This is different than
- the amazons3 sync tool extension, which exceutes AWS CLI command as
+ the amazons3 sync tool extension, which executes AWS CLI command as
the same user that is running the tool.)
</para>
<para>
+ When using physical media via the standard store action, there is an
+ implicit limit to the size of a backup, since a backup must fit on a
+ single disc. Since there is no physical media, no such limit exists
+ for Amazon S3 backups. This leaves open the possibility that Cedar
+ Backup might construct an unexpectedly-large backup that the
+ administrator is not aware of. Over time, this might become
+ expensive, either in terms of network bandwidth or in terms of Amazon
+ S3 storage and I/O charges. To mitigate this risk, set a reasonable
+ maximum size using the configuration elements shown below. If the
+ backup fails, you have a chance to review what made the backup larger
+ than you expected, and you can either correct the problem (i.e. remove
+ a large temporary directory that got inadvertently included in the
+ backup) or change configuration to take into account the new "normal"
+ maximum size.
+ </para>
+
+ <para>
You can optionally configure Cedar Backup to encrypt data before
sending it to S3. To do that, provide a complete command line using
the <literal>${input}</literal> and <literal>${output}</literal>
@@ -251,7 +268,39 @@
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><literal>full_size_limit</literal></term>
+ <listitem>
+ <para>Maximum size of a full backup, in bytes</para>
+ <para>
+ If this field is provided, then a size limit will be applied
+ to full backups. If the total size of the selected staging
+ directory is greater than the limit, then the backup will
+ fail.
+ </para>
+ <para>
+ <emphasis>Restrictions:</emphasis> If provided, must be an integer greater than zero.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>incr_size_limit</literal></term>
+ <listitem>
+ <para>Maximum size of an incremental backup, in bytes</para>
+ <para>
+ If this field is provided, then a size limit will be applied
+ to incremental backups. If the total size of the selected
+ staging directory is greater than the limit, then the backup
+ will fail.
+ </para>
+ <para>
+ <emphasis>Restrictions:</emphasis> If provided, must be an integer greater than zero.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</sect1>
Modified: cedar-backup2/trunk/testcase/amazons3tests.py
===================================================================
--- cedar-backup2/trunk/testcase/amazons3tests.py 2014-11-17 21:51:30 UTC (rev 1095)
+++ cedar-backup2/trunk/testcase/amazons3tests.py 2015-01-05 20:24:25 UTC (rev 1096)
@@ -9,7 +9,7 @@
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
-# Copyright (c) 2014 Kenneth J. Pronovici.
+# Copyright (c) 2014-2015 Kenneth J. Pronovici.
# All rights reserved.
#
# This program is free software; you can redistribute it and/or
@@ -145,49 +145,40 @@
"""
Test constructor with no values filled in.
"""
- amazons3 = AmazonS3Config()
+ amazons3 = AmazonS3Config()
self.failUnlessEqual(False, amazons3.warnMidnite)
self.failUnlessEqual(None, amazons3.s3Bucket)
self.failUnlessEqual(None, amazons3.encryptCommand)
+ self.failUnlessEqual(None, amazons3.fullBackupSizeLimit)
+ self.failUnlessEqual(None, amazons3.incrementalBackupSizeLimit)
def testConstructor_002(self):
"""
Test constructor with all values filled in, with valid values.
"""
- amazons3 = AmazonS3Config(True, "bucket", "encrypt")
+ amazons3 = AmazonS3Config(True, "bucket", "encrypt", 1, 2)
self.failUnlessEqual(True, amazons3.warnMidnite)
self.failUnlessEqual("bucket", amazons3.s3Bucket)
self.failUnlessEqual("encrypt", amazons3.encryptCommand)
+ self.failUnlessEqual(1L, amazons3.fullBackupSizeLimit)
+ self.failUnlessEqual(2L, amazons3.incrementalBackupSizeLimit)
def testConstructor_003(self):
"""
- Test assignment of s3Bucket attribute, None value.
- """
- amazons3 = AmazonS3Config(warnMidnite=True, s3Bucket="bucket", encryptCommand="encrypt")
- self.failUnlessEqual(True, amazons3.warnMidnite)
- self.failUnlessEqual("bucket", amazons3.s3Bucket)
- self.failUnlessEqual("encrypt", amazons3.encryptCommand)
- amazons3.s3Bucket = None
- self.failUnlessEqual(True, amazons3.warnMidnite)
- self.failUnlessEqual(None, amazons3.s3Bucket)
- self.failUnlessEqual("encrypt", amazons3.encryptCommand)
-
- def testConstructor_004(self):
- """
Test assignment of warnMidnite attribute, valid value (real boolean).
"""
- amazons3 = AmazonS3Config()
+ amazons3 = AmazonS3Config()
self.failUnlessEqual(False, amazons3.warnMidnite)
amazons3.warnMidnite = True
self.failUnlessEqual(True, amazons3.warnMidnite)
amazons3.warnMidnite = False
self.failUnlessEqual(False, amazons3.warnMidnite)
- def testConstructor_005(self):
+ def testConstructor_004(self):
"""
Test assignment of warnMidnite attribute, valid value (expression).
"""
- amazons3 = AmazonS3Config()
+ amazons3 = AmazonS3Config()
self.failUnlessEqual(False, amazons3.warnMidnite)
amazons3.warnMidnite = 0
self.failUnlessEqual(False, amazons3.warnMidnite)
@@ -200,11 +191,20 @@
amazons3.warnMidnite = 3
self.failUnlessEqual(True, amazons3.warnMidnite)
+ def testConstructor_005(self):
+ """
+ Test assignment of s3Bucket attribute, None value.
+ """
+ amazons3 = AmazonS3Config(s3Bucket="bucket")
+ self.failUnlessEqual("bucket", amazons3.s3Bucket)
+ amazons3.s3Bucket = None
+ self.failUnlessEqual(None, amazons3.s3Bucket)
+
def testConstructor_006(self):
"""
Test assignment of s3Bucket attribute, valid value.
"""
- amazons3 = AmazonS3Config()
+ amazons3 = AmazonS3Config()
self.failUnlessEqual(None, amazons3.s3Bucket)
amazons3.s3Bucket = "bucket"
self.failUnlessEqual("bucket", amazons3.s3Bucket)
@@ -213,30 +213,111 @@
"""
Test assignment of s3Bucket attribute, invalid value (empty).
"""
- amazons3 = AmazonS3Config()
+ amazons3 = AmazonS3Config()
self.failUnlessEqual(None, amazons3.s3Bucket)
self.failUnlessAssignRaises(ValueError, amazons3, "s3Bucket", "")
self.failUnlessEqual(None, amazons3.s3Bucket)
def testConstructor_008(self):
"""
+ Test assignment of encryptCommand attribute, None value.
+ """
+ amazons3 = AmazonS3Config(encryptCommand="encrypt")
+ self.failUnlessEqual("encrypt", amazons3.encryptCommand)
+ amazons3.encryptCommand = None
+ self.failUnlessEqual(None, amazons3.encryptCommand)
+
+ def testConstructor_009(self):
+ """
Test assignment of encryptCommand attribute, valid value.
"""
- amazons3 = AmazonS3Config()
+ amazons3 = AmazonS3Config()
self.failUnlessEqual(None, amazons3.encryptCommand)
amazons3.encryptCommand = "encrypt"
self.failUnlessEqual("encrypt", amazons3.encryptCommand)
- def testConstructor_009(self):
+ def testConstructor_010(self):
"""
Test assignment of encryptCommand attribute, invalid value (empty).
"""
- amazons3 = AmazonS3Config()
+ amazons3 = AmazonS3Config()
self.failUnlessEqual(None, amazons3.encryptCommand)
self.failUnlessAssignRaises(ValueError, amazons3, "encryptCommand", "")
self.failUnlessEqual(None, amazons3.encryptCommand)
+ def testConstructor_011(self):
+ """
+ Test assignment of fullBackupSizeLimit attribute, None value.
+ """
+ amazons3 = AmazonS3Config(fullBackupSizeLimit=100)
+ self.failUnlessEqual(100L, amazons3.fullBackupSizeLimit)
+ amazons3.fullBackupSizeLimit = None
+ self.failUnlessEqual(None, amazons3.fullBackupSizeLimit)
+ def testConstructor_012(self):
+ """
+ Test assignment of fullBackupSizeLimit attribute, valid long value.
+ """
+ amazons3 = AmazonS3Config()
+ self.failUnlessEqual(None, amazons3.fullBackupSizeLimit)
+ amazons3.fullBackupSizeLimit = 7516192768L
+ self.failUnlessEqual(7516192768L, amazons3.fullBackupSizeLimit)
+
+ def testConstructor_013(self):
+ """
+ Test assignment of fullBackupSizeLimit attribute, valid string value.
+ """
+ amazons3 = AmazonS3Config()
+ self.failUnlessEqual(None, amazons3.fullBackupSizeLimit)
+ amazons3.fullBackupSizeLimit = "7516192768"
+ self.failUnlessEqual(7516192768L, amazons3.fullBackupSizeLimit)
+
+ def testConstructor_014(self):
+ """
+ Test assignment of fullBackupSizeLimit attribute, invalid value.
+ """
+ amazons3 = AmazonS3Config()
+ self.failUnlessEqual(None, amazons3.fullBackupSizeLimit)
+ self.failUnlessAssignRaises(ValueError, amazons3, "fullBackupSizeLimit", "xxx")
+ self.failUnlessEqual(None, amazons3.fullBackupSizeLimit)
+
+ def testConstructor_015(self):
+ """
+ Test assignment of incrementalBackupSizeLimit attribute, None value.
+ """
+ amazons3 = AmazonS3Config(incrementalBackupSizeLimit=100)
+ self.failUnlessEqual(100L, amazons3.incrementalBackupSizeLimit)
+ amazons3.incrementalBackupSizeLimit = None
+ self.failUnlessEqual(None, amazons3.incrementalBackupSizeLimit)
+
+ def testConstructor_016(self):
+ """
+ Test assignment of incrementalBackupSizeLimit attribute, valid long value.
+ """
+ amazons3 = AmazonS3Config()
+ self.failUnlessEqual(None, amazons3.incrementalBackupSizeLimit)
+ amazons3.incrementalBackupSizeLimit = 7516192768L
+ self.failUnlessEqual(7516192768L, amazons3.incrementalBackupSizeLimit)
+
+ def testConstructor_017(self):
+ """
+ Test assignment of incrementalBackupSizeLimit attribute, valid string value.
+ """
+ amazons3 = AmazonS3Config()
+ self.failUnlessEqual(None, amazons3.incrementalBackupSizeLimit)
+ amazons3.incrementalBackupSizeLimit = "7516192768"
+ self.failUnlessEqual(7516192768L, amazons3.incrementalBackupSizeLimit)
+
+ def testConstructor_018(self):
+ """
+ Test assignment of incrementalBackupSizeLimit attribute, invalid value.
+ """
+ amazons3 = AmazonS3Config()
+ self.failUnlessEqual(None, amazons3.incrementalBackupSizeLimit)
+ self.failUnlessAssignRaises(ValueError, amazons3, "incrementalBackupSizeLimit", "xxx")
+ self.failUnlessEqual(None, amazons3.incrementalBackupSizeLimit)
+
+
############################
# Test comparison operators
############################
@@ -259,8 +340,8 @@
"""
Test comparison of two identical objects, all attributes non-None.
"""
- amazons31 = AmazonS3Config(True, "bucket", "encrypt")
- amazons32 = AmazonS3Config(True, "bucket", "encrypt")
+ amazons31 = AmazonS3Config(True, "bucket", "encrypt", 1, 2)
+ amazons32 = AmazonS3Config(True, "bucket", "encrypt", 1, 2)
self.failUnlessEqual(amazons31, amazons32)
self.failUnless(amazons31 == amazons32)
self.failUnless(not amazons31 < amazons32)
@@ -301,8 +382,8 @@
"""
Test comparison of two differing objects, s3Bucket differs.
"""
- amazons31 = AmazonS3Config(True, "bucket1", "encrypt")
- amazons32 = AmazonS3Config(True, "bucket2", "encrypt")
+ amazons31 = AmazonS3Config(s3Bucket="bucket1")
+ amazons32 = AmazonS3Config(s3Bucket="bucket2")
self.failIfEqual(amazons31, amazons32)
self.failUnless(not amazons31 == amazons32)
self.failUnless(amazons31 < amazons32)
@@ -329,8 +410,8 @@
"""
Test comparison of two differing objects, encryptCommand differs.
"""
- amazons31 = AmazonS3Config(True, "bucket", "encrypt1")
- amazons32 = AmazonS3Config(True, "bucket", "encrypt2")
+ amazons31 = AmazonS3Config(encryptCommand="encrypt1")
+ amazons32 = AmazonS3Config(encryptCommand="encrypt2")
self.failIfEqual(amazons31, amazons32)
self.failUnless(not amazons31 == amazons32)
self.failUnless(amazons31 < amazons32)
@@ -339,7 +420,63 @@
self.failUnless(not amazons31 >= amazons32)
self.failUnless(amazons31 != amazons32)
+ def testComparison_008(self):
+ """
+ Test comparison of two differing objects, fullBackupSizeLimit differs (one None).
+ """
+ amazons31 = AmazonS3Config()
+ amazons32 = AmazonS3Config(fullBackupSizeLimit=1L)
+ self.failIfEqual(amazons31, amazons32)
+ self.failUnless(not amazons31 == amazons32)
+ self.failUnless(amazons31 < amazons32)
+ self.failUnless(amazons31 <= amazons32)
+ self.failUnless(not amazons31 > amazons32)
+ self.failUnless(not amazons31 >= amazons32)
+ self.failUnless(amazons31 != amazons32)
+ def testComparison_009(self):
+ """
+ Test comparison of two differing objects, fullBackupSizeLimit differs.
+ """
+ amazons31 = AmazonS3Config(fullBackupSizeLimit=1L)
+ amazons32 = AmazonS3Config(fullBackupSizeLimit=2L)
+ self.failIfEqual(amazons31, amazons32)
+ self.failUnless(not amazons31 == amazons32)
+ self.failUnless(amazons31 < amazons32)
+ self.failUnless(amazons31 <= amazons32)
+ self.failUnless(not amazons31 > amazons32)
+ self.failUnless(not amazons31 >= amazons32)
+ self.failUnless(amazons31 != amazons32)
+
+ def testComparison_010(self):
+ """
+ Test comparison of two differing objects, incrementalBackupSizeLimit differs (one None).
+ """
+ amazons31 = AmazonS3Config()
+ amazons32 = AmazonS3Config(incrementalBackupSizeLimit=1L)
+ self.failIfEqual(amazons31, amazons32)
+ self.failUnless(not amazons31 == amazons32)
+ self.failUnless(amazons31 < amazons32)
+ self.failUnless(amazons31 <= amazons32)
+ self.failUnless(not amazons31 > amazons32)
+ self.failUnless(not amazons31 >= amazons32)
+ self.failUnless(amazons31 != amazons32)
+
+ def testComparison_011(self):
+ """
+ Test comparison of two differing objects, incrementalBackupSizeLimit differs.
+ """
+ amazons31 = AmazonS3Config(incrementalBackupSizeLimit=1L)
+ amazons32 = AmazonS3Config(incrementalBackupSizeLimit=2L)
+ self.failIfEqual(amazons31, amazons32)
+ self.failUnless(not amazons31 == amazons32)
+ self.failUnless(amazons31 < amazons32)
+ self.failUnless(amazons31 <= amazons32)
+ self.failUnless(not amazons31 > amazons32)
+ self.failUnless(not amazons31 >= amazons32)
+ self.failUnless(amazons31 != amazons32)
+
+
########################
# TestLocalConfig class
########################
@@ -435,7 +572,7 @@
Test assignment of amazons3 attribute, None value.
"""
config = LocalConfig()
- config.amazons3 = None
+ config.amazons3 = None
self.failUnlessEqual(None, config.amazons3)
def testConstructor_005(self):
@@ -443,7 +580,7 @@
Test assignment of amazons3 attribute, valid value.
"""
config = LocalConfig()
- config.amazons3 = AmazonS3Config()
+ config.amazons3 = AmazonS3Config()
self.failUnlessEqual(AmazonS3Config(), config.amazons3)
def testConstructor_006(self):
@@ -477,10 +614,10 @@
Test comparison of two identical objects, all attributes non-None.
"""
config1 = LocalConfig()
- config1.amazons3 = AmazonS3Config()
+ config1.amazons3 = AmazonS3Config()
config2 = LocalConfig()
- config2.amazons3 = AmazonS3Config()
+ config2.amazons3 = AmazonS3Config()
self.failUnlessEqual(config1, config2)
self.failUnless(config1 == config2)
@@ -496,7 +633,7 @@
"""
config1 = LocalConfig()
config2 = LocalConfig()
- config2.amazons3 = AmazonS3Config()
+ config2.amazons3 = AmazonS3Config()
self.failIfEqual(config1, config2)
self.failUnless(not config1 == config2)
self.failUnless(config1 < config2)
@@ -510,10 +647,10 @@
Test comparison of two differing objects, s3Bucket differs.
"""
config1 = LocalConfig()
- config1.amazons3 = AmazonS3Config(True, "bucket1", "encrypt")
+ config1.amazons3 = AmazonS3Config(True, "bucket1", "encrypt", 1, 2)
config2 = LocalConfig()
- config2.amazons3 = AmazonS3Config(True, "bucket2", "encrypt")
+ config2.amazons3 = AmazonS3Config(True, "bucket2", "encrypt", 1, 2)
self.failIfEqual(config1, config2)
self.failUnless(not config1 == config2)
@@ -533,7 +670,7 @@
Test validate on a None amazons3 section.
"""
config = LocalConfig()
- config.amazons3 = None
+ config.amazons3 = None
self.failUnlessRaises(ValueError, config.validate)
def testValidate_002(self):
@@ -541,7 +678,7 @@
Test validate on an empty amazons3 section.
"""
config = LocalConfig()
- config.amazons3 = AmazonS3Config()
+ config.amazons3 = AmazonS3Config()
self.failUnlessRaises(ValueError, config.validate)
def testValidate_003(self):
@@ -549,7 +686,7 @@
Test validate on a non-empty amazons3 section with no values filled in.
"""
config = LocalConfig()
- config.amazons3 = AmazonS3Config(None)
+ config.amazons3 = AmazonS3Config(None)
self.failUnlessRaises(ValueError, config.validate)
def testValidate_005(self):
@@ -557,7 +694,7 @@
Test validate on a non-empty amazons3 section with valid values filled in.
"""
config = LocalConfig()
- config.amazons3 = AmazonS3Config(True, "bucket")
+ config.amazons3 = AmazonS3Config(True, "bucket")
config.validate()
@@ -589,11 +726,15 @@
self.failUnlessEqual(True, config.amazons3.warnMidnite)
self.failUnlessEqual("mybucket", config.amazons3.s3Bucket)
self.failUnlessEqual("encrypt", config.amazons3.encryptCommand)
+ self.failUnlessEqual(5368709120L, config.amazons3.fullBackupSizeLimit)
+ self.failUnlessEqual(2147483648, config.amazons3.incrementalBackupSizeLimit)
config = LocalConfig(xmlData=contents, validate=False)
self.failIfEqual(None, config.amazons3)
self.failUnlessEqual(True, config.amazons3.warnMidnite)
self.failUnlessEqual("mybucket", config.amazons3.s3Bucket)
self.failUnlessEqual("encrypt", config.amazons3.encryptCommand)
+ self.failUnlessEqual(5368709120L, config.amazons3.fullBackupSizeLimit)
+ self.failUnlessEqual(2147483648, config.amazons3.incrementalBackupSizeLimit)
###################
@@ -604,18 +745,18 @@
"""
Test with empty config document.
"""
- amazons3 = AmazonS3Config()
+ amazons3 = AmazonS3Config()
config = LocalConfig()
- config.amazons3 = amazons3
+ config.amazons3 = amazons3
self.validateAddConfig(config)
def testAddConfig_002(self):
"""
Test with values set.
"""
- amazons3 = AmazonS3Config(True, "bucket", "encrypt")
+ amazons3 = AmazonS3Config(True, "bucket", "encrypt", 1, 2)
config = LocalConfig()
- config.amazons3 = amazons3
+ config.amazons3 = amazons3
self.validateAddConfig(config)
Modified: cedar-backup2/trunk/testcase/data/amazons3.conf.2
===================================================================
--- cedar-backup2/trunk/testcase/data/amazons3.conf.2 2014-11-17 21:51:30 UTC (rev 1095)
+++ cedar-backup2/trunk/testcase/data/amazons3.conf.2 2015-01-05 20:24:25 UTC (rev 1096)
@@ -5,5 +5,7 @@
<warn_midnite>Y</warn_midnite>
<s3_bucket>mybucket</s3_bucket>
<encrypt>encrypt</encrypt>
+ <full_size_limit>5368709120</full_size_limit> <!-- 5 GB -->
+ <incr_size_limit>2147483648</incr_size_limit> <!-- 2 GB -->
</amazons3>
</cb_config>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2014-11-17 21:51:32
|
Revision: 1095
http://sourceforge.net/p/cedar-backup/code/1095
Author: pronovic
Date: 2014-11-17 21:51:30 +0000 (Mon, 17 Nov 2014)
Log Message:
-----------
Reference Cloudbees for continuous integration
Modified Paths:
--------------
web/trunk/cedar-backup/config/footer.gth
web/trunk/cedar-backup/config/site-wide.gth
web/trunk/cedar-backup/source/index.gtml
Modified: web/trunk/cedar-backup/config/footer.gth
===================================================================
--- web/trunk/cedar-backup/config/footer.gth 2014-10-08 02:11:26 UTC (rev 1094)
+++ web/trunk/cedar-backup/config/footer.gth 2014-11-17 21:51:30 UTC (rev 1095)
@@ -31,8 +31,9 @@
</div>
<div id="sourceforge">
- <h3><span>Project Hosted By:</span</h3>
+ <h3><span>Project Hosting:</span</h3>
<<SF_LOGO>>
+ <<CLOUDBEES_LOGO>>
</div>
</div> <!-- end id="sidebar" -->
Modified: web/trunk/cedar-backup/config/site-wide.gth
===================================================================
--- web/trunk/cedar-backup/config/site-wide.gth 2014-10-08 02:11:26 UTC (rev 1094)
+++ web/trunk/cedar-backup/config/site-wide.gth 2014-11-17 21:51:30 UTC (rev 1095)
@@ -32,3 +32,6 @@
#define DEBIAN_URL http://debian.org/
#define SF_LOGO <a href="http://sourceforge.net"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=210468&type=2" width="125" height="37" border="0" alt="SourceForge.net Logo" /></a>
+#define CLOUDBEES_LOGO <a href="https://cedar-solutions.ci.cloudbees.com/"><img src="http://www.cloudbees.com/sites/default/files/styles/large/public/Button-Powered-by-CB.png" width="130" border="0" alt="Cloudbees Logo" /></a>
+#define DEVATCLOUD_LOGO <a href="https://cedar-solutions.ci.cloudbees.com/"><img src="https://www.cloudbees.com/sites/default/files/styles/large/public/Button-Built-on-CB-1.png" border="0" alt="DEV@cloud Logo" /></a>
+
Modified: web/trunk/cedar-backup/source/index.gtml
===================================================================
--- web/trunk/cedar-backup/source/index.gtml 2014-10-08 02:11:26 UTC (rev 1094)
+++ web/trunk/cedar-backup/source/index.gtml 2014-11-17 21:51:30 UTC (rev 1095)
@@ -171,6 +171,16 @@
online.
</p>
+<a name="ci"></a>
+<h2>Continuous Integration</h2>
+
+<p>
+Continuous integration via <a href="https://cedar-solutions.ci.cloudbees.com">Jenkins</a>
+is graciously hosted by CloudBees using their Dev@cloud solution.
+</p>
+
+<<DEVATCLOUD_LOGO>>
+
#include "content_footer.gth"
#include "footer.gth"
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2014-10-08 02:11:29
|
Revision: 1094
http://sourceforge.net/p/cedar-backup/code/1094
Author: pronovic
Date: 2014-10-08 02:11:26 +0000 (Wed, 08 Oct 2014)
Log Message:
-----------
Tagging the 2.24.1 release of Cedar Backup.
Added Paths:
-----------
cedar-backup2/tags/CEDAR_BACKUP2_V2.24.1/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2014-10-08 00:32:06
|
Revision: 1092
http://sourceforge.net/p/cedar-backup/code/1092
Author: pronovic
Date: 2014-10-08 00:32:03 +0000 (Wed, 08 Oct 2014)
Log Message:
-----------
Tagging the 2.24.0 release of Cedar Backup.
Added Paths:
-----------
cedar-backup2/tags/CEDAR_BACKUP2_V2.24.0/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2014-10-08 00:31:55
|
Revision: 1091
http://sourceforge.net/p/cedar-backup/code/1091
Author: pronovic
Date: 2014-10-08 00:31:46 +0000 (Wed, 08 Oct 2014)
Log Message:
-----------
Tagging new version of 2.24.0 release of Cedar Backup.
Removed Paths:
-------------
cedar-backup2/tags/CEDAR_BACKUP2_V2.24.0/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2014-10-08 00:31:12
|
Revision: 1090
http://sourceforge.net/p/cedar-backup/code/1090
Author: pronovic
Date: 2014-10-08 00:31:04 +0000 (Wed, 08 Oct 2014)
Log Message:
-----------
Document chardet dependency
Modified Paths:
--------------
cedar-backup2/trunk/manual/src/depends.xml
Modified: cedar-backup2/trunk/manual/src/depends.xml
===================================================================
--- cedar-backup2/trunk/manual/src/depends.xml 2014-10-08 00:20:36 UTC (rev 1089)
+++ cedar-backup2/trunk/manual/src/depends.xml 2014-10-08 00:31:04 UTC (rev 1090)
@@ -583,6 +583,31 @@
</para>
<para>
+ After you install AWS CLI, you need to configure your connection
+ to AWS with an appropriate access id and access key. Amazon provides a good
+ <ulink url="http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-set-up.html">setup guide</ulink>.
+ </para>
+
+ <informaltable>
+ <tgroup cols="2">
+ <colspec colnum="1" colwidth="1*"/>
+ <colspec colnum="2" colwidth="3.5*"/>
+ <thead>
+ <row>
+ <entry>Source</entry>
+ <entry>URL</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>upstream</entry>
+ <entry><ulink url="http://aws.amazon.com/documentation/cli/"/></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <para>
The initial implementation of the amazons3 extension was written
using AWS CLI 1.4. As of this writing, not all Linux distributions
include a package for this version. On these platforms, the
@@ -590,11 +615,18 @@
and then <code>pip install awscli</code>. The Debian package includes
an appropriate dependency starting with the jesse release.
</para>
-
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>Chardet</command></term>
+ <listitem>
+
<para>
- After you install AWS CLI, you need to configure your connection
- to AWS with an appropriate access id and access key. Amazon provides a good
- <ulink url="http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-set-up.html">setup guide</ulink>.
+ The <command>cback-amazons3-sync</command> command relies on the
+ Chardet python package to check filename encoding. You only need
+ this package if you are going to use the sync tool.
</para>
<informaltable>
@@ -610,8 +642,12 @@
<tbody>
<row>
<entry>upstream</entry>
- <entry><ulink url="http://aws.amazon.com/documentation/cli/"/></entry>
+ <entry><ulink url="https://github.com/chardet/chardet"/></entry>
</row>
+ <row>
+ <entry>debian</entry>
+ <entry><ulink url="https://packages.debian.org/stable/python-chardet"/></entry>
+ </row>
</tbody>
</tgroup>
</informaltable>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2014-10-08 00:20:44
|
Revision: 1089
http://sourceforge.net/p/cedar-backup/code/1089
Author: pronovic
Date: 2014-10-08 00:20:36 +0000 (Wed, 08 Oct 2014)
Log Message:
-----------
Tagging the 2.24.0 release of Cedar Backup.
Added Paths:
-----------
cedar-backup2/tags/CEDAR_BACKUP2_V2.24.0/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2014-10-08 00:20:02
|
Revision: 1088
http://sourceforge.net/p/cedar-backup/code/1088
Author: pronovic
Date: 2014-10-08 00:19:58 +0000 (Wed, 08 Oct 2014)
Log Message:
-----------
Release 2.24.0
Modified Paths:
--------------
cedar-backup2/trunk/CedarBackup2/release.py
cedar-backup2/trunk/Changelog
Modified: cedar-backup2/trunk/CedarBackup2/release.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/release.py 2014-10-08 00:18:15 UTC (rev 1087)
+++ cedar-backup2/trunk/CedarBackup2/release.py 2014-10-08 00:19:58 UTC (rev 1088)
@@ -34,7 +34,7 @@
AUTHOR = "Kenneth J. Pronovici"
EMAIL = "pro...@ie..."
COPYRIGHT = "2004-2011,2013,2014"
-VERSION = "2.23.3"
-DATE = "03 Oct 2014"
+VERSION = "2.24.0"
+DATE = "07 Oct 2014"
URL = "http://cedar-backup.sourceforge.net/"
Modified: cedar-backup2/trunk/Changelog
===================================================================
--- cedar-backup2/trunk/Changelog 2014-10-08 00:18:15 UTC (rev 1087)
+++ cedar-backup2/trunk/Changelog 2014-10-08 00:19:58 UTC (rev 1088)
@@ -1,4 +1,4 @@
-Version 2.23.4 unreleased
+Version 2.24.0 07 Oct 2014
* Implement a new tool called cback-amazons3-sync.
* Add support for missing --diagnostics flag in cback-span script.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2014-10-08 00:18:18
|
Revision: 1087
http://sourceforge.net/p/cedar-backup/code/1087
Author: pronovic
Date: 2014-10-08 00:18:15 +0000 (Wed, 08 Oct 2014)
Log Message:
-----------
Fix typos
Modified Paths:
--------------
cedar-backup2/trunk/manual/src/commandline.xml
Modified: cedar-backup2/trunk/manual/src/commandline.xml
===================================================================
--- cedar-backup2/trunk/manual/src/commandline.xml 2014-10-07 22:29:07 UTC (rev 1086)
+++ cedar-backup2/trunk/manual/src/commandline.xml 2014-10-08 00:18:15 UTC (rev 1087)
@@ -406,7 +406,7 @@
Before you use this extension, you need to set up your Amazon S3
account and configure AWS CLI as detailed in Amazons's
<ulink url="http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-set-up.html">setup guide</ulink>.
- The <command>aws</command> will be executed as the same user that
+ The <command>aws</command> command will be executed as the same user that
is executing the <command>cback-amazons3-sync</command> command, so
make sure you configure it as the proper user. (This is different
than the amazons3 extension, which is designed to execute as root
@@ -633,7 +633,7 @@
<para>
To avoid confusion, the <command>cback-amazons3-sync</command>
tries to guess which files in the source directory will
- cause problems, and refuses to execute AWS CLI S3 sync if
+ cause problems, and refuses to execute the AWS CLI S3 sync if
any problematic files exist. If you'd rather proceed
anyway, use <option>--ignoreWarnings</option>.
</para>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2014-10-07 22:29:17
|
Revision: 1086
http://sourceforge.net/p/cedar-backup/code/1086
Author: pronovic
Date: 2014-10-07 22:29:07 +0000 (Tue, 07 Oct 2014)
Log Message:
-----------
Start writing user manual for cback-amazons3-sync
Modified Paths:
--------------
cedar-backup2/trunk/CedarBackup2/tools/amazons3.py
cedar-backup2/trunk/manual/src/commandline.xml
cedar-backup2/trunk/manual/src/extensions.xml
Modified: cedar-backup2/trunk/CedarBackup2/tools/amazons3.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/tools/amazons3.py 2014-10-07 21:56:46 UTC (rev 1085)
+++ cedar-backup2/trunk/CedarBackup2/tools/amazons3.py 2014-10-07 22:29:07 UTC (rev 1086)
@@ -916,36 +916,37 @@
fd.write(" Cedar Backup Amazon S3 sync tool.\n")
fd.write("\n")
fd.write(" This Cedar Backup utility synchronizes a local directory to an Amazon S3\n")
- fd.write(" bucket. After the sync is complete, a validation step is takane. An\n")
- fd.write(" error is reported if the contents of the bucket do not match \n")
- fd.write(" the source directory, or if the indicated size for any file differs.\n")
+ fd.write(" bucket. After the sync is complete, a validation step is taken. An\n")
+ fd.write(" error is reported if the contents of the bucket do not match the\n")
+ fd.write(" source directory, or if the indicated size for any file differs.\n")
fd.write(" This tool is a wrapper over the AWS CLI command-line tool.\n")
fd.write("\n")
fd.write(" The following arguments are required:\n")
fd.write("\n")
- fd.write(" sourceDir The local source directory on disk (must exist)\n")
- fd.write(" s3BucketUrl The URL to the target Amazon S3 bucket\n")
+ fd.write(" sourceDir The local source directory on disk (must exist)\n")
+ fd.write(" s3BucketUrl The URL to the target Amazon S3 bucket\n")
fd.write("\n")
fd.write(" The following switches are accepted:\n")
fd.write("\n")
- fd.write(" -h, --help Display this usage/help listing\n")
- fd.write(" -V, --version Display version information\n")
- fd.write(" -b, --verbose Print verbose output as well as logging to disk\n")
- fd.write(" -q, --quiet Run quietly (display no output to the screen)\n")
- fd.write(" -l, --logfile Path to logfile (default: %s)\n" % DEFAULT_LOGFILE)
- fd.write(" -o, --owner Logfile ownership, user:group (default: %s:%s)\n" % (DEFAULT_OWNERSHIP[0], DEFAULT_OWNERSHIP[1]))
- fd.write(" -m, --mode Octal logfile permissions mode (default: %o)\n" % DEFAULT_MODE)
- fd.write(" -O, --output Record some sub-command (i.e. aws) output to the log\n")
- fd.write(" -d, --debug Write debugging information to the log (implies --output)\n")
- fd.write(" -s, --stack Dump a Python stack trace instead of swallowing exceptions\n") # exactly 80 characters in width!
- fd.write(" -D, --diagnostics Print runtime diagnostics to the screen and exit\n")
- fd.write(" -v, --verifyOnly Only verify the S3 bucket contents, do not make changes\n")
+ fd.write(" -h, --help Display this usage/help listing\n")
+ fd.write(" -V, --version Display version information\n")
+ fd.write(" -b, --verbose Print verbose output as well as logging to disk\n")
+ fd.write(" -q, --quiet Run quietly (display no output to the screen)\n")
+ fd.write(" -l, --logfile Path to logfile (default: %s)\n" % DEFAULT_LOGFILE)
+ fd.write(" -o, --owner Logfile ownership, user:group (default: %s:%s)\n" % (DEFAULT_OWNERSHIP[0], DEFAULT_OWNERSHIP[1]))
+ fd.write(" -m, --mode Octal logfile permissions mode (default: %o)\n" % DEFAULT_MODE)
+ fd.write(" -O, --output Record some sub-command (i.e. aws) output to the log\n")
+ fd.write(" -d, --debug Write debugging information to the log (implies --output)\n")
+ fd.write(" -s, --stack Dump Python stack trace instead of swallowing exceptions\n") # exactly 80 characters in width!
+ fd.write(" -D, --diagnostics Print runtime diagnostics to the screen and exit\n")
+ fd.write(" -v, --verifyOnly Only verify the S3 bucket contents, do not make changes\n")
+ fd.write(" -w, --ignoreWarnings Ignore warnings about problematic filename encodings\n")
fd.write("\n")
fd.write(" Typical usage would be something like:\n")
fd.write("\n")
- fd.write(" cback-amazons3-sync /home/myuser/subdir s3://example.com-backup/myuser\n")
+ fd.write(" cback-amazons3-sync /home/myuser s3://example.com-backup/myuser\n")
fd.write("\n")
- fd.write(" This will sync the contents of /home/myuser/subdir into the indiated bucket.\n")
+ fd.write(" This will sync the contents of /home/myuser into the indicated bucket.\n")
fd.write("\n")
Modified: cedar-backup2/trunk/manual/src/commandline.xml
===================================================================
--- cedar-backup2/trunk/manual/src/commandline.xml 2014-10-07 21:56:46 UTC (rev 1085)
+++ cedar-backup2/trunk/manual/src/commandline.xml 2014-10-07 22:29:07 UTC (rev 1086)
@@ -43,15 +43,25 @@
<title>Overview</title>
<para>
- Cedar Backup comes with two command-line programs, the
- <command>cback</command> and <command>cback-span</command> commands.
+ Cedar Backup comes with three command-line programs:
+ <command>cback</command>, <command>cback-amazons3-sync</command>, and
+ <command>cback-span</command>.
+ </para>
+
+ <para>
The <command>cback</command> command is the primary command line
interface and the only Cedar Backup program that most users will ever
need.
</para>
<para>
- Users that have a <emphasis>lot</emphasis> of data to back up —
+ The <command>cback-amazons3-sync</command> tool is used for
+ synchronizing entire directories of files up to an Amazon S3 cloud
+ storage bucket, outside of the normal Cedar Backup process.
+ </para>
+
+ <para>
+ Users who have a <emphasis>lot</emphasis> of data to back up —
more than will fit on a single CD or DVD — can use the
interactive <command>cback-span</command> tool to split their data
between multiple discs.
@@ -364,6 +374,289 @@
<!-- ################################################################# -->
+ <sect1 id="cedar-commandline-sync">
+
+ <title>The <command>cback-amazons3-sync</command> command</title>
+
+ <!-- ################################################################# -->
+
+ <sect2 id="cedar-commandline-sync-intro">
+
+ <title>Introduction</title>
+
+ <para>
+ The <command>cback-amazons3-sync</command> tool is used for
+ synchronizing entire directories of files up to an Amazon S3 cloud
+ storage bucket, outside of the normal Cedar Backup process.
+ </para>
+
+ <para>
+ This might be a good option for some types of data, as long as you
+ understand the limitations around retrieving previous versions of
+ objects that get modified or deleted as part of a sync. S3 does
+ support versioning, but it won't be quite as easy to get at those
+ previous versions as with an explicit incremental backup like
+ <command>cback</command> provides. Cedar Backup does not provide
+ any tooling that would help you retrieve previous versions.
+ </para>
+
+ <para>
+ The underlying functionality relies on the
+ <ulink url="http://aws.amazon.com/documentation/cli/">AWS CLI</ulink> toolset.
+ Before you use this extension, you need to set up your Amazon S3
+ account and configure AWS CLI as detailed in Amazons's
+ <ulink url="http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-set-up.html">setup guide</ulink>.
+ The <command>aws</command> will be executed as the same user that
+ is executing the <command>cback-amazons3-sync</command> command, so
+ make sure you configure it as the proper user. (This is different
+ than the amazons3 extension, which is designed to execute as root
+ and switches over to the configured backup user to execute AWS CLI
+ commands.)
+ </para>
+
+ </sect2>
+
+ <!-- ################################################################# -->
+
+ <sect2 id="cedar-commandline-sync-syntax">
+
+ <title>Syntax</title>
+
+ <para>
+ The <command>cback-amazons3-sync</command> command has the following syntax:
+ </para>
+
+ <screen>
+ Usage: cback-amazons3-sync [switches] sourceDir s3bucketUrl
+
+ Cedar Backup Amazon S3 sync tool.
+
+ This Cedar Backup utility synchronizes a local directory to an Amazon S3
+ bucket. After the sync is complete, a validation step is taken. An
+ error is reported if the contents of the bucket do not match the
+ source directory, or if the indicated size for any file differs.
+ This tool is a wrapper over the AWS CLI command-line tool.
+
+ The following arguments are required:
+
+ sourceDir The local source directory on disk (must exist)
+ s3BucketUrl The URL to the target Amazon S3 bucket
+
+ The following switches are accepted:
+
+ -h, --help Display this usage/help listing
+ -V, --version Display version information
+ -b, --verbose Print verbose output as well as logging to disk
+ -q, --quiet Run quietly (display no output to the screen)
+ -l, --logfile Path to logfile (default: /var/log/cback.log)
+ -o, --owner Logfile ownership, user:group (default: root:adm)
+ -m, --mode Octal logfile permissions mode (default: 640)
+ -O, --output Record some sub-command (i.e. aws) output to the log
+ -d, --debug Write debugging information to the log (implies --output)
+ -s, --stack Dump Python stack trace instead of swallowing exceptions
+ -D, --diagnostics Print runtime diagnostics to the screen and exit
+ -v, --verifyOnly Only verify the S3 bucket contents, do not make changes
+ -w, --ignoreWarnings Ignore warnings about problematic filename encodings
+
+ Typical usage would be something like:
+
+ cback-amazons3-sync /home/myuser s3://example.com-backup/myuser
+
+ This will sync the contents of /home/myuser into the indicated bucket.
+ </screen>
+
+ </sect2>
+
+
+ <!-- ################################################################# -->
+
+ <sect2 id="cedar-commandline-sync-options">
+
+ <title>Switches</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><option>-h</option>, <option>--help</option></term>
+ <listitem>
+ <para>Display usage/help listing.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-V</option>, <option>--version</option></term>
+ <listitem>
+ <para>Display version information.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-b</option>, <option>--verbose</option></term>
+ <listitem>
+ <para>
+ Print verbose output to the screen as well writing to the
+ logfile. When this option is enabled, most information
+ that would normally be written to the logfile will also be
+ written to the screen.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-q</option>, <option>--quiet</option></term>
+ <listitem>
+ <para>Run quietly (display no output to the screen).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-l</option>, <option>--logfile</option></term>
+ <listitem>
+ <para>
+ Specify the path to an alternate logfile. The default
+ logfile file is <filename>/var/log/cback.log</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-o</option>, <option>--owner</option></term>
+ <listitem>
+ <para>
+ Specify the ownership of the logfile, in the form
+ <literal>user:group</literal>. The default ownership is
+ <literal>root:adm</literal>, to match the Debian standard
+ for most logfiles. This value will only be used when
+ creating a new logfile. If the logfile already exists when
+ the <command>cback-amazons3-sync</command> command is
+ executed, it will retain its existing ownership and mode.
+ Only user and group names may be used, not numeric uid and
+ gid values.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-m</option>, <option>--mode</option></term>
+ <listitem>
+ <para>
+ Specify the permissions for the logfile, using the
+ numeric mode as in chmod(1). The default mode is
+ <literal>0640</literal> (<literal>-rw-r-----</literal>).
+ This value will only be used when creating a new logfile.
+ If the logfile already exists when the
+ <command>cback-amazons3-sync</command> command is executed,
+ it will retain its existing ownership and mode.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-O</option>, <option>--output</option></term>
+ <listitem>
+ <para>
+ Record some sub-command output to the logfile. When this
+ option is enabled, all output from system commands will be
+ logged. This might be useful for debugging or just for
+ reference.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-d</option>, <option>--debug</option></term>
+ <listitem>
+ <para>
+ Write debugging information to the logfile. This option
+ produces a high volume of output, and would generally only
+ be needed when debugging a problem. This option implies
+ the <option>--output</option> option, as well.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-s</option>, <option>--stack</option></term>
+ <listitem>
+ <para>
+ Dump a Python stack trace instead of swallowing
+ exceptions. This forces Cedar Backup to dump the entire
+ Python stack trace associated with an error, rather than
+ just propagating last message it received back up to the
+ user interface. Under some circumstances, this is useful
+ information to include along with a bug report.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-D</option>, <option>--diagnostics</option></term>
+ <listitem>
+ <para>
+ Display runtime diagnostic information and then exit.
+ This diagnostic information is often useful when filing a
+ bug report.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-v</option>, <option>--verifyOnly</option></term>
+ <listitem>
+ <para>
+ Only verify the S3 bucket contents against the directory
+ on disk. Do not make any changes to the S3 bucket or
+ transfer any files. This is intended as a quick check
+ to see whether the sync is up-to-date.
+ </para>
+
+ <para>
+ Although no files are transferred, the tool will still
+ execute the source filename encoding check, discussed
+ below along with <option>--ignoreWarnings</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-w</option>, <option>--ignoreWarnings</option></term>
+ <listitem>
+ <para>
+ The AWS CLI S3 sync process is very picky about filename
+ encoding. Files that the Linux filesystem handles with no
+ problems can cause problems in S3 if the filename cannot be
+ encoded properly in your configured locale. As of this
+ writing, filenames like this will cause the sync process
+ to abort without transferring all files as expected.
+ </para>
+
+ <para>
+ To avoid confusion, the <command>cback-amazons3-sync</command>
+ tries to guess which files in the source directory will
+ cause problems, and refuses to execute AWS CLI S3 sync if
+ any problematic files exist. If you'd rather proceed
+ anyway, use <option>--ignoreWarnings</option>.
+ </para>
+
+ <para>
+ If problematic files are found, then you have basically
+ two options: either correct your locale (i.e. if you have
+ set <literal>LANG=C</literal>) or rename the file so it
+ can be encoded properly in your locale. The error messages
+ will tell you the expected encoding (from your locale) and
+ the actual detected encoding for the filename.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </sect2>
+
+ </sect1>
+
+ <!-- ################################################################# -->
+
<sect1 id="cedar-commandline-cbackspan">
<title>The <command>cback-span</command> command</title>
Modified: cedar-backup2/trunk/manual/src/extensions.xml
===================================================================
--- cedar-backup2/trunk/manual/src/extensions.xml 2014-10-07 21:56:46 UTC (rev 1085)
+++ cedar-backup2/trunk/manual/src/extensions.xml 2014-10-07 22:29:07 UTC (rev 1086)
@@ -113,8 +113,10 @@
<ulink url="http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-set-up.html">setup guide</ulink>.
The extension assumes that the backup is being executed as root, and
switches over to the configured backup user to run the
- <literal>aws</literal> program. So, make sure you configure the AWS
- CLI tools as the backup user and not root.
+ <command>aws</command> program. So, make sure you configure the AWS
+ CLI tools as the backup user and not root. (This is different than
+ the amazons3 sync tool extension, which exceutes AWS CLI command as
+ the same user that is running the tool.)
</para>
<para>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2014-10-07 21:56:51
|
Revision: 1085
http://sourceforge.net/p/cedar-backup/code/1085
Author: pronovic
Date: 2014-10-07 21:56:46 +0000 (Tue, 07 Oct 2014)
Log Message:
-----------
Continued development on s3 sync tool
Modified Paths:
--------------
cedar-backup2/trunk/CedarBackup2/tools/amazons3.py
cedar-backup2/trunk/doc/cback-amazons3-sync.1
cedar-backup2/trunk/testcase/synctests.py
Modified: cedar-backup2/trunk/CedarBackup2/tools/amazons3.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/tools/amazons3.py 2014-10-07 21:52:19 UTC (rev 1084)
+++ cedar-backup2/trunk/CedarBackup2/tools/amazons3.py 2014-10-07 21:56:46 UTC (rev 1085)
@@ -56,11 +56,16 @@
import os
import logging
import getopt
+import json
+import chardet
+import warnings
# Cedar Backup modules
from CedarBackup2.release import AUTHOR, EMAIL, VERSION, DATE, COPYRIGHT
+from CedarBackup2.filesystem import FilesystemList
from CedarBackup2.cli import setupLogging, DEFAULT_LOGFILE, DEFAULT_OWNERSHIP, DEFAULT_MODE
from CedarBackup2.util import Diagnostics, splitCommandLine, encodePath
+from CedarBackup2.util import executeCommand
########################################################################
@@ -69,10 +74,13 @@
logger = logging.getLogger("CedarBackup2.log.tools.amazons3")
-SHORT_SWITCHES = "hVbql:o:m:OdsDv"
+AWS_COMMAND = [ "aws" ]
+
+SHORT_SWITCHES = "hVbql:o:m:OdsDvw"
LONG_SWITCHES = [ 'help', 'version', 'verbose', 'quiet',
'logfile=', 'owner=', 'mode=',
- 'output', 'debug', 'stack', 'diagnostics', "verifyOnly", ]
+ 'output', 'debug', 'stack', 'diagnostics',
+ 'verifyOnly', 'ignoreWarnings', ]
#######################################################################
@@ -189,6 +197,7 @@
self._stacktrace = False
self._diagnostics = False
self._verifyOnly = False
+ self._ignoreWarnings = False
self._sourceDir = None
self._s3BucketUrl = None
if argumentList is not None and argumentString is not None:
@@ -291,6 +300,11 @@
return -1
else:
return 1
+ if self.ignoreWarnings != other.ignoreWarnings:
+ if self.ignoreWarnings < other.ignoreWarnings:
+ return -1
+ else:
+ return 1
if self.sourceDir != other.sourceDir:
if self.sourceDir < other.sourceDir:
return -1
@@ -518,6 +532,22 @@
"""
return self._verifyOnly
+ def _setIgnoreWarnings(self, value):
+ """
+ Property target used to set the ignoreWarnings flag.
+ No validations, but we normalize the value to C{True} or C{False}.
+ """
+ if value:
+ self._ignoreWarnings = True
+ else:
+ self._ignoreWarnings = False
+
+ def _getIgnoreWarnings(self):
+ """
+ Property target used to get the ignoreWarnings flag.
+ """
+ return self._ignoreWarnings
+
def _setSourceDir(self, value):
"""
Property target used to set the sourceDir parameter.
@@ -560,6 +590,7 @@
stacktrace = property(_getStacktrace, _setStacktrace, None, "Command-line stacktrace (C{-s,--stack}) flag.")
diagnostics = property(_getDiagnostics, _setDiagnostics, None, "Command-line diagnostics (C{-D,--diagnostics}) flag.")
verifyOnly = property(_getVerifyOnly, _setVerifyOnly, None, "Command-line verifyOnly (C{-v,--verifyOnly}) flag.")
+ ignoreWarnings = property(_getIgnoreWarnings, _setIgnoreWarnings, None, "Command-line ignoreWarnings (C{-w,--ignoreWarnings}) flag.")
sourceDir = property(_getSourceDir, _setSourceDir, None, "Command-line sourceDir, source of sync.")
s3BucketUrl = property(_getS3BucketUrl, _setS3BucketUrl, None, "Command-line s3BucketUrl, target of sync.")
@@ -643,6 +674,8 @@
argumentList.append("--diagnostics")
if self.verifyOnly:
argumentList.append("--verifyOnly")
+ if self.ignoreWarnings:
+ argumentList.append("--ignoreWarnings")
if self.sourceDir is not None:
argumentList.append(self.sourceDir)
if self.s3BucketUrl is not None:
@@ -703,6 +736,8 @@
argumentString += "--diagnostics "
if self.verifyOnly:
argumentString += "--verifyOnly "
+ if self.ignoreWarnings:
+ argumentString += "--ignoreWarnings "
if self.sourceDir is not None:
argumentString += "\"%s\" " % self.sourceDir
if self.s3BucketUrl is not None:
@@ -764,6 +799,8 @@
self.diagnostics = True
if switches.has_key("-v") or switches.has_key("--verifyOnly"):
self.verifyOnly = True
+ if switches.has_key("-w") or switches.has_key("--ignoreWarnings"):
+ self.ignoreWarnings = True
try:
(self.sourceDir, self.s3BucketUrl) = remaining
except ValueError:
@@ -839,6 +876,7 @@
logger.info("Cedar Backup Amazon S3 sync run started.")
logger.info("Options were [%s]" % options)
logger.info("Logfile is [%s]" % logfile)
+ Diagnostics().logDiagnostics(method=logger.info)
if options.stacktrace:
_executeAction(options)
@@ -964,15 +1002,161 @@
@raise Exception: Under many generic error conditions
"""
- if not os.path.isdir(options.sourceDir):
- raise Exception("Source directory does not exist on disk.")
+ sourceFiles = _buildSourceFiles(options.sourceDir)
+ if not options.ignoreWarnings:
+ _checkSourceFiles(options.sourceDir, sourceFiles)
+ if not options.verifyOnly:
+ _synchronizeBucket(options.sourceDir, options.s3BucketUrl)
+ _verifyBucketContents(options.sourceDir, sourceFiles, options.s3BucketUrl)
+################################
+# _buildSourceFiles() function
+################################
+
+def _buildSourceFiles(sourceDir):
+ """
+ Build a list of files in a source directory
+ @param sourceDir: Local source directory
+ @return: FilesystemList with contents of source directory
+ """
+ if not os.path.isdir(sourceDir):
+ raise ValueError("Source directory does not exist on disk.")
+ sourceFiles = FilesystemList()
+ sourceFiles.addDirContents(sourceDir)
+ return sourceFiles
+
+
+###############################
+# _checkSourceFiles() function
+###############################
+
+def _checkSourceFiles(sourceDir, sourceFiles):
+ """
+ Check source files, trying to guess which ones will have encoding problems.
+ @param sourceDir: Local source directory
+ @param sourceDir: Local source directory
+ @raises ValueError: If a problem file is found
+ @see U{http://opensourcehacker.com/2011/09/16/fix-linux-filename-encodings-with-python/}
+ @see U{http://serverfault.com/questions/82821/how-to-tell-the-language-encoding-of-a-filename-on-linux}
+ @see U{http://randysofia.com/2014/06/06/aws-cli-and-your-locale/}
+ """
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore") # So we don't print unicode warnings from comparisons
+
+ encoding = Diagnostics().encoding
+
+ failed = False
+ for entry in sourceFiles:
+ result = chardet.detect(entry)
+ source = entry.decode(result["encoding"])
+ try:
+ target = source.encode(encoding)
+ if source != target:
+ logger.error("Inconsistent encoding for [%s]: got %s, but need %s" % (entry, result["encoding"], encoding))
+ failed = True
+ except UnicodeEncodeError:
+ logger.error("Inconsistent encoding for [%s]: got %s, but need %s" % (entry, result["encoding"], encoding))
+ failed = True
+
+ if not failed:
+ logger.info("Completed checking source filename encoding (no problems found).")
+ else:
+ logger.error("Some filenames have inconsistent encodings and will likely cause sync problems.")
+ logger.error("You may be able to fix this by setting a more sensible locale in your environment.")
+ logger.error("Aternately, you can rename the problem files to be valid in the indicated locale.")
+ logger.error("To ignore this warning and proceed anyway, use --ignoreWarnings")
+ raise ValueError("Some filenames have inconsistent encodings and will likely cause sync problems.")
+
+
+################################
+# _synchronizeBucket() function
+################################
+
+def _synchronizeBucket(sourceDir, s3BucketUrl):
+ """
+ Synchronize a local directory to an Amazon S3 bucket.
+ @param sourceDir: Local source directory
+ @param s3BucketUrl: Target S3 bucket URL
+ """
+ logger.info("Synchronizing local source directory up to Amazon S3.")
+ args = [ "s3", "sync", sourceDir, s3BucketUrl, "--delete", "--recursive", ]
+ result = executeCommand(AWS_COMMAND, args, returnOutput=False)[0]
+ if result != 0:
+ raise IOError("Error [%d] calling AWS CLI synchronize bucket." % result)
+
+
+###################################
+# _verifyBucketContents() function
+###################################
+
+def _verifyBucketContents(sourceDir, sourceFiles, s3BucketUrl):
+ """
+ Verify that a source directory is equivalent to an Amazon S3 bucket.
+ @param sourceDir: Local source directory
+ @param sourceFiles: Filesystem list containing contents of source directory
+ @param s3BucketUrl: Target S3 bucket URL
+ """
+ # As of this writing, the documentation for the S3 API that we're using
+ # below says that up to 1000 elements at a time are returned, and that we
+ # have to manually handle pagination by looking for the IsTruncated element.
+ # However, in practice, this is not true. I have been testing with
+ # "aws-cli/1.4.4 Python/2.7.3 Linux/3.2.0-4-686-pae", installed through PIP.
+ # No matter how many items exist in my bucket and prefix, I get back a
+ # single JSON result. I've tested with buckets containing nearly 6000
+ # elements.
+ #
+ # If I turn on debugging, it's clear that underneath, something in the API
+ # is executing multiple list-object requests against AWS, and stiching
+ # results together to give me back the final JSON result. The debug output
+ # clearly incldues multiple requests, and each XML response (except for the
+ # final one) contains <IsTruncated>true</IsTruncated>.
+ #
+ # This feature is not mentioned in the offical changelog for any of the
+ # releases going back to 1.0.0. It appears to happen in the botocore
+ # library, but I'll admit I can't actually find the code that implements it.
+ # For now, all I can do is rely on this behavior and hope that the
+ # documentation is out-of-date. I'm not going to write code that tries to
+ # parse out IsTruncated if I can't actually test that code.
+
+ (bucket, prefix) = s3BucketUrl.replace("s3://", "").split("/", 1)
+
+ query = "Contents[].{Key: Key, Size: Size}"
+ args = [ "s3api", "list-objects", "--bucket", bucket, "--prefix", prefix, "--query", query, ]
+ (result, data) = executeCommand(AWS_COMMAND, args, returnOutput=True)
+ if result != 0:
+ raise IOError("Error [%d] calling AWS CLI verify bucket contents." % result)
+
+ contents = { }
+ for entry in json.loads("".join(data)):
+ key = entry["Key"].replace(prefix, "")
+ size = long(entry["Size"])
+ contents[key] = size
+
+ failed = False
+ for entry in sourceFiles:
+ if os.path.isfile(entry):
+ key = entry.replace(sourceDir, "")
+ size = long(os.stat(entry).st_size)
+ if not key in contents:
+ logger.error("File was apparently not uploaded: [%s]" % entry)
+ failed = True
+ else:
+ if size != contents[key]:
+ logger.error("File size differs [%s]: expected %s bytes but got %s bytes" % (entry, size, contents[key]))
+ failed = True
+
+ if not failed:
+ logger.info("Completed verifying Amazon S3 bucket contents (no problems found).")
+ else:
+ logger.error("There were differences between source directory and target S3 bucket.")
+ raise ValueError("There were differences between source directory and target S3 bucket.")
+
+
#########################################################################
# Main routine
########################################################################
if __name__ == "__main__":
- result = cli()
- sys.exit(result)
+ sys.exit(cli())
Modified: cedar-backup2/trunk/doc/cback-amazons3-sync.1
===================================================================
--- cedar-backup2/trunk/doc/cback-amazons3-sync.1 2014-10-07 21:52:19 UTC (rev 1084)
+++ cedar-backup2/trunk/doc/cback-amazons3-sync.1 2014-10-07 21:56:46 UTC (rev 1085)
@@ -10,8 +10,8 @@
.\" # Author : Kenneth J. Pronovici <pro...@ie...>
.\" # Language : nroff
.\" # Project : Cedar Backup, release 2
-.\" # Revision : $Id: cback-span.1 1011 2010-07-10 23:58:29Z pronovic $
-.\" # Purpose : Manpage for cback-span script
+.\" # Revision : $Id$
+.\" # Purpose : Manpage for cback-amazons3-sync script
.\" #
.\" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
.\"
@@ -114,16 +114,17 @@
.SH NOTES
.PP
This tool is a wrapper over the Amazon AWS CLI interface found in the aws(1)
-command.
+command. Specifically, cback\-amazons3\-sync invokes "aws s3 sync" followed by
+"aws s3api list-objects".
.PP
Cedar Backup itself is designed to run as root. However, this command can be
run safely as any user that is configured to use the Amazon AWS CLI interface.
-The aws(1) command will be executed by the same user which is executing the
-cback-amazons3-sync.
+The aws(1) command will be executed by the same user which is executing
+cback\-amazons3\-sync.
.PP
You must configure the AWS CLI interface to have a valid connection to Amazon
-S3 infrastructure before using this command. For more information about how to
-accomplish this, see the Cedar Backup user guide.
+S3 infrastructure before using cback\-amazons3\-sync. For more information
+about how to accomplish this, see the Cedar Backup user guide.
.SH SEE ALSO
cback(1)
.SH FILES
Modified: cedar-backup2/trunk/testcase/synctests.py
===================================================================
--- cedar-backup2/trunk/testcase/synctests.py 2014-10-07 21:52:19 UTC (rev 1084)
+++ cedar-backup2/trunk/testcase/synctests.py 2014-10-07 21:56:46 UTC (rev 1085)
@@ -188,6 +188,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -208,6 +209,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -228,6 +230,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -248,6 +251,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -268,6 +272,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -288,6 +293,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -308,6 +314,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -328,6 +335,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -348,6 +356,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -368,6 +377,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -388,6 +398,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -408,6 +419,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -428,6 +440,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -448,6 +461,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -468,6 +482,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -488,6 +503,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -508,6 +524,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -528,6 +545,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -548,6 +566,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -568,6 +587,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -612,6 +632,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -632,6 +653,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -652,6 +674,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -672,6 +695,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -740,6 +764,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -760,6 +785,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -780,6 +806,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -800,6 +827,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -868,6 +896,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -888,6 +917,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -908,6 +938,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -928,6 +959,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -948,6 +980,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -968,6 +1001,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -988,6 +1022,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1008,6 +1043,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1028,6 +1064,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1048,6 +1085,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1068,6 +1106,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1088,6 +1127,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1108,6 +1148,7 @@
self.failUnlessEqual(True, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1128,6 +1169,7 @@
self.failUnlessEqual(True, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1148,6 +1190,7 @@
self.failUnlessEqual(True, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1168,6 +1211,7 @@
self.failUnlessEqual(True, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1188,6 +1232,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(True, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1208,6 +1253,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(True, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1228,6 +1274,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(True, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1248,6 +1295,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(True, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1268,6 +1316,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(True, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1288,6 +1337,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(True, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1308,6 +1358,7 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(True, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
@@ -1328,11 +1379,96 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(True, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
def testConstructor_082(self):
"""
+ Test constructor with argumentList=["--ignoreWarnings", ], validate=False.
+ """
+ options = Options(argumentList=["--ignoreWarnings", ], validate=False)
+ self.failUnlessEqual(False, options.help)
+ self.failUnlessEqual(False, options.version)
+ self.failUnlessEqual(False, options.verbose)
+ self.failUnlessEqual(False, options.quiet)
+ self.failUnlessEqual(None, options.logfile)
+ self.failUnlessEqual(None, options.owner)
+ self.failUnlessEqual(None, options.mode)
+ self.failUnlessEqual(False, options.output)
+ self.failUnlessEqual(False, options.debug)
+ self.failUnlessEqual(False, options.stacktrace)
+ self.failUnlessEqual(False, options.diagnostics)
+ self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(True, options.ignoreWarnings)
+ self.failUnlessEqual(None, options.sourceDir)
+ self.failUnlessEqual(None, options.s3BucketUrl)
+
+ def testConstructor_083(self):
+ """
+ Test constructor with argumentString="--ignoreWarnings", validate=False.
+ """
+ options = Options(argumentString="--ignoreWarnings", validate=False)
+ self.failUnlessEqual(False, options.help)
+ self.failUnlessEqual(False, options.version)
+ self.failUnlessEqual(False, options.verbose)
+ self.failUnlessEqual(False, options.quiet)
+ self.failUnlessEqual(None, options.logfile)
+ self.failUnlessEqual(None, options.owner)
+ self.failUnlessEqual(None, options.mode)
+ self.failUnlessEqual(False, options.output)
+ self.failUnlessEqual(False, options.debug)
+ self.failUnlessEqual(False, options.stacktrace)
+ self.failUnlessEqual(False, options.diagnostics)
+ self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(True, options.ignoreWarnings)
+ self.failUnlessEqual(None, options.sourceDir)
+ self.failUnlessEqual(None, options.s3BucketUrl)
+
+ def testConstructor_084(self):
+ """
+ Test constructor with argumentList=["-w", ], validate=False.
+ """
+ options = Options(argumentList=["-w", ], validate=False)
+ self.failUnlessEqual(False, options.help)
+ self.failUnlessEqual(False, options.version)
+ self.failUnlessEqual(False, options.verbose)
+ self.failUnlessEqual(False, options.quiet)
+ self.failUnlessEqual(None, options.logfile)
+ self.failUnlessEqual(None, options.owner)
+ self.failUnlessEqual(None, options.mode)
+ self.failUnlessEqual(False, options.output)
+ self.failUnlessEqual(False, options.debug)
+ self.failUnlessEqual(False, options.stacktrace)
+ self.failUnlessEqual(False, options.diagnostics)
+ self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(True, options.ignoreWarnings)
+ self.failUnlessEqual(None, options.sourceDir)
+ self.failUnlessEqual(None, options.s3BucketUrl)
+
+ def testConstructor_085(self):
+ """
+ Test constructor with argumentString="-w", validate=False.
+ """
+ options = Options(argumentString="-w", validate=False)
+ self.failUnlessEqual(False, options.help)
+ self.failUnlessEqual(False, options.version)
+ self.failUnlessEqual(False, options.verbose)
+ self.failUnlessEqual(False, options.quiet)
+ self.failUnlessEqual(None, options.logfile)
+ self.failUnlessEqual(None, options.owner)
+ self.failUnlessEqual(None, options.mode)
+ self.failUnlessEqual(False, options.output)
+ self.failUnlessEqual(False, options.debug)
+ self.failUnlessEqual(False, options.stacktrace)
+ self.failUnlessEqual(False, options.diagnostics)
+ self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(True, options.ignoreWarnings)
+ self.failUnlessEqual(None, options.sourceDir)
+ self.failUnlessEqual(None, options.s3BucketUrl)
+
+ def testConstructor_086(self):
+ """
Test constructor with argumentList=["source", "bucket", ], validate=False.
"""
options = Options(argumentList=[ "source", "bucket", ], validate=False)
@@ -1348,10 +1484,11 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual("source", options.sourceDir)
self.failUnlessEqual("bucket", options.s3BucketUrl)
- def testConstructor_083(self):
+ def testConstructor_087(self):
"""
Test constructor with argumentString="source bucket", validate=False.
"""
@@ -1368,10 +1505,11 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual("source", options.sourceDir)
self.failUnlessEqual("bucket", options.s3BucketUrl)
- def testConstructor_084(self):
+ def testConstructor_088(self):
"""
Test constructor with argumentList=["-d", "--verbose", "-O", "--mode", "600", "source", "bucket", ], validate=False.
"""
@@ -1388,10 +1526,11 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual("source", options.sourceDir)
self.failUnlessEqual("bucket", options.s3BucketUrl)
- def testConstructor_085(self):
+ def testConstructor_089(self):
"""
Test constructor with argumentString="-d --verbose -O --mode 600 source bucket", validate=False.
"""
@@ -1408,22 +1547,23 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual("source", options.sourceDir)
self.failUnlessEqual("bucket", options.s3BucketUrl)
- def testConstructor_086(self):
+ def testConstructor_090(self):
"""
Test constructor with argumentList=[], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=[], validate=True)
- def testConstructor_087(self):
+ def testConstructor_091(self):
"""
Test constructor with argumentString="", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="", validate=True)
- def testConstructor_088(self):
+ def testConstructor_092(self):
"""
Test constructor with argumentList=["--help", ], validate=True.
"""
@@ -1440,10 +1580,11 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
- def testConstructor_089(self):
+ def testConstructor_093(self):
"""
Test constructor with argumentString="--help", validate=True.
"""
@@ -1460,10 +1601,11 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
- def testConstructor_099(self):
+ def testConstructor_094(self):
"""
Test constructor with argumentList=["-h", ], validate=True.
"""
@@ -1480,10 +1622,11 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
- def testConstructor_100(self):
+ def testConstructor_095(self):
"""
Test constructor with argumentString="-h", validate=True.
"""
@@ -1500,10 +1643,11 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
- def testConstructor_101(self):
+ def testConstructor_096(self):
"""
Test constructor with argumentList=["--version", ], validate=True.
"""
@@ -1520,10 +1664,11 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
- def testConstructor_102(self):
+ def testConstructor_097(self):
"""
Test constructor with argumentString="--version", validate=True.
"""
@@ -1540,10 +1685,11 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
- def testConstructor_103(self):
+ def testConstructor_098(self):
"""
Test constructor with argumentList=["-V", ], validate=True.
"""
@@ -1560,10 +1706,11 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
- def testConstructor_104(self):
+ def testConstructor_099(self):
"""
Test constructor with argumentString="-V", validate=True.
"""
@@ -1580,322 +1727,323 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(False, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
- def testConstructor_105(self):
+ def testConstructor_100(self):
"""
Test constructor with argumentList=["--verbose", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["--verbose", ], validate=True)
- def testConstructor_106(self):
+ def testConstructor_101(self):
"""
Test constructor with argumentString="--verbose", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="--verbose", validate=True)
- def testConstructor_107(self):
+ def testConstructor_102(self):
"""
Test constructor with argumentList=["-b", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["-b", ], validate=True)
- def testConstructor_108(self):
+ def testConstructor_103(self):
"""
Test constructor with argumentString="-b", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="-b", validate=True)
- def testConstructor_109(self):
+ def testConstructor_104(self):
"""
Test constructor with argumentList=["--quiet", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["--quiet", ], validate=True)
- def testConstructor_110(self):
+ def testConstructor_105(self):
"""
Test constructor with argumentString="--quiet", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="--quiet", validate=True)
- def testConstructor_111(self):
+ def testConstructor_106(self):
"""
Test constructor with argumentList=["-q", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["-q", ], validate=True)
- def testConstructor_112(self):
+ def testConstructor_107(self):
"""
Test constructor with argumentString="-q", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="-q", validate=True)
- def testConstructor_113(self):
+ def testConstructor_108(self):
"""
Test constructor with argumentList=["--logfile", ], validate=True.
"""
self.failUnlessRaises(GetoptError, Options, argumentList=["--logfile", ], validate=True)
- def testConstructor_114(self):
+ def testConstructor_109(self):
"""
Test constructor with argumentString="--logfile", validate=True.
"""
self.failUnlessRaises(GetoptError, Options, argumentString="--logfile", validate=True)
- def testConstructor_115(self):
+ def testConstructor_110(self):
"""
Test constructor with argumentList=["-l", ], validate=True.
"""
self.failUnlessRaises(GetoptError, Options, argumentList=["-l", ], validate=True)
- def testConstructor_116(self):
+ def testConstructor_111(self):
"""
Test constructor with argumentString="-l", validate=True.
"""
self.failUnlessRaises(GetoptError, Options, argumentString="-l", validate=True)
- def testConstructor_117(self):
+ def testConstructor_112(self):
"""
Test constructor with argumentList=["--logfile", "something", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["--logfile", "something", ], validate=True)
- def testConstructor_118(self):
+ def testConstructor_113(self):
"""
Test constructor with argumentString="--logfile something", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="--logfile something", validate=True)
- def testConstructor_119(self):
+ def testConstructor_114(self):
"""
Test constructor with argumentList=["-l", "something", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["-l", "something", ], validate=True)
- def testConstructor_120(self):
+ def testConstructor_115(self):
"""
Test constructor with argumentString="-l something", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="-l something", validate=True)
- def testConstructor_121(self):
+ def testConstructor_116(self):
"""
Test constructor with argumentList=["--owner", ], validate=True.
"""
self.failUnlessRaises(GetoptError, Options, argumentList=["--owner", ], validate=True)
- def testConstructor_122(self):
+ def testConstructor_117(self):
"""
Test constructor with argumentString="--owner", validate=True.
"""
self.failUnlessRaises(GetoptError, Options, argumentString="--owner", validate=True)
- def testConstructor_123(self):
+ def testConstructor_118(self):
"""
Test constructor with argumentList=["-o", ], validate=True.
"""
self.failUnlessRaises(GetoptError, Options, argumentList=["-o", ], validate=True)
- def testConstructor_124(self):
+ def testConstructor_119(self):
"""
Test constructor with argumentString="-o", validate=True.
"""
self.failUnlessRaises(GetoptError, Options, argumentString="-o", validate=True)
- def testConstructor_125(self):
+ def testConstructor_120(self):
"""
Test constructor with argumentList=["--owner", "something", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["--owner", "something", ], validate=True)
- def testConstructor_126(self):
+ def testConstructor_121(self):
"""
Test constructor with argumentString="--owner something", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="--owner something", validate=True)
- def testConstructor_127(self):
+ def testConstructor_122(self):
"""
Test constructor with argumentList=["-o", "something", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["-o", "something", ], validate=True)
- def testConstructor_128(self):
+ def testConstructor_123(self):
"""
Test constructor with argumentString="-o something", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="-o something", validate=True)
- def testConstructor_129(self):
+ def testConstructor_124(self):
"""
Test constructor with argumentList=["--owner", "a:b", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["--owner", "a:b", ], validate=True)
- def testConstructor_130(self):
+ def testConstructor_125(self):
"""
Test constructor with argumentString="--owner a:b", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="--owner a:b", validate=True)
- def testConstructor_131(self):
+ def testConstructor_126(self):
"""
Test constructor with argumentList=["-o", "a:b", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["-o", "a:b", ], validate=True)
- def testConstructor_132(self):
+ def testConstructor_127(self):
"""
Test constructor with argumentString="-o a:b", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="-o a:b", validate=True)
- def testConstructor_133(self):
+ def testConstructor_128(self):
"""
Test constructor with argumentList=["--mode", ], validate=True.
"""
self.failUnlessRaises(GetoptError, Options, argumentList=["--mode", ], validate=True)
- def testConstructor_134(self):
+ def testConstructor_129(self):
"""
Test constructor with argumentString="--mode", validate=True.
"""
self.failUnlessRaises(GetoptError, Options, argumentString="--mode", validate=True)
- def testConstructor_135(self):
+ def testConstructor_130(self):
"""
Test constructor with argumentList=["-m", ], validate=True.
"""
self.failUnlessRaises(GetoptError, Options, argumentList=["-m", ], validate=True)
- def testConstructor_136(self):
+ def testConstructor_131(self):
"""
Test constructor with argumentString="-m", validate=True.
"""
self.failUnlessRaises(GetoptError, Options, argumentString="-m", validate=True)
- def testConstructor_137(self):
+ def testConstructor_132(self):
"""
Test constructor with argumentList=["--mode", "something", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["--mode", "something", ], validate=True)
- def testConstructor_138(self):
+ def testConstructor_133(self):
"""
Test constructor with argumentString="--mode something", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="--mode something", validate=True)
- def testConstructor_139(self):
+ def testConstructor_134(self):
"""
Test constructor with argumentList=["-m", "something", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["-m", "something", ], validate=True)
- def testConstructor_140(self):
+ def testConstructor_135(self):
"""
Test constructor with argumentString="-m something", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="-m something", validate=True)
- def testConstructor_141(self):
+ def testConstructor_136(self):
"""
Test constructor with argumentList=["--mode", "631", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["--mode", "631", ], validate=True)
- def testConstructor_142(self):
+ def testConstructor_137(self):
"""
Test constructor with argumentString="--mode 631", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="--mode 631", validate=True)
- def testConstructor_143(self):
+ def testConstructor_138(self):
"""
Test constructor with argumentList=["-m", "631", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["-m", "631", ], validate=True)
- def testConstructor_144(self):
+ def testConstructor_139(self):
"""
Test constructor with argumentString="-m 631", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="-m 631", validate=True)
- def testConstructor_145(self):
+ def testConstructor_140(self):
"""
Test constructor with argumentList=["--output", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["--output", ], validate=True)
- def testConstructor_146(self):
+ def testConstructor_141(self):
"""
Test constructor with argumentString="--output", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="--output", validate=True)
- def testConstructor_147(self):
+ def testConstructor_142(self):
"""
Test constructor with argumentList=["-O", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["-O", ], validate=True)
- def testConstructor_148(self):
+ def testConstructor_143(self):
"""
Test constructor with argumentString="-O", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="-O", validate=True)
- def testConstructor_149(self):
+ def testConstructor_144(self):
"""
Test constructor with argumentList=["--debug", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["--debug", ], validate=True)
- def testConstructor_150(self):
+ def testConstructor_145(self):
"""
Test constructor with argumentString="--debug", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="--debug", validate=True)
- def testConstructor_151(self):
+ def testConstructor_146(self):
"""
Test constructor with argumentList=["-d", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["-d", ], validate=True)
- def testConstructor_152(self):
+ def testConstructor_147(self):
"""
Test constructor with argumentString="-d", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="-d", validate=True)
- def testConstructor_153(self):
+ def testConstructor_148(self):
"""
Test constructor with argumentList=["--stack", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["--stack", ], validate=True)
- def testConstructor_154(self):
+ def testConstructor_149(self):
"""
Test constructor with argumentString="--stack", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="--stack", validate=True)
- def testConstructor_155(self):
+ def testConstructor_150(self):
"""
Test constructor with argumentList=["-s", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["-s", ], validate=True)
- def testConstructor_156(self):
+ def testConstructor_151(self):
"""
Test constructor with argumentString="-s", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="-s", validate=True)
- def testConstructor_157(self):
+ def testConstructor_152(self):
"""
Test constructor with argumentList=["--diagnostics", ], validate=True.
"""
@@ -1912,10 +2060,11 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(True, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
- def testConstructor_158(self):
+ def testConstructor_153(self):
"""
Test constructor with argumentString="--diagnostics", validate=True.
"""
@@ -1932,10 +2081,11 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(True, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
- def testConstructor_159(self):
+ def testConstructor_154(self):
"""
Test constructor with argumentList=["-D", ], validate=True.
"""
@@ -1952,10 +2102,11 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(True, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
- def testConstructor_160(self):
+ def testConstructor_155(self):
"""
Test constructor with argumentString="-D", validate=True.
"""
@@ -1972,35 +2123,60 @@
self.failUnlessEqual(False, options.stacktrace)
self.failUnlessEqual(True, options.diagnostics)
self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(False, options.ignoreWarnings)
self.failUnlessEqual(None, options.sourceDir)
self.failUnlessEqual(None, options.s3BucketUrl)
- def testConstructor_161(self):
+ def testConstructor_156(self):
"""
Test constructor with argumentList=["--verifyOnly", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["--verifyOnly", ], validate=True)
- def testConstructor_162(self):
+ def testConstructor_157(self):
"""
Test constructor with argumentString="--verifyOnly", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="--verifyOnly", validate=True)
- def testConstructor_163(self):
+ def testConstructor_158(self):
"""
Test constructor with argumentList=["-v", ], validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentList=["-v", ], validate=True)
- def testConstructor_164(self):
+ def testConstructor_159(self):
"""
Test constructor with argumentString="-v", validate=True.
"""
self.failUnlessRaises(ValueError, Options, argumentString="-v", validate=True)
- def testConstructor_165(self):
+ def testConstructor_160(self):
"""
+ Test constructor with argumentList=["--ignoreWarnings", ], validate=True.
+ """
+ self.failUnlessRaises(ValueError, Options, argumentList=["--ignoreWarnings", ], validate=True)
+
+ def testConstructor_161(self):
...
[truncated message content] |
|
From: <pro...@us...> - 2014-10-07 21:52:23
|
Revision: 1084
http://sourceforge.net/p/cedar-backup/code/1084
Author: pronovic
Date: 2014-10-07 21:52:19 +0000 (Tue, 07 Oct 2014)
Log Message:
-----------
Take result var out of global scope
Modified Paths:
--------------
cedar-backup2/trunk/CedarBackup2/tools/span.py
Modified: cedar-backup2/trunk/CedarBackup2/tools/span.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/tools/span.py 2014-10-07 19:17:12 UTC (rev 1083)
+++ cedar-backup2/trunk/CedarBackup2/tools/span.py 2014-10-07 21:52:19 UTC (rev 1084)
@@ -719,6 +719,5 @@
########################################################################
if __name__ == "__main__":
- result = cli()
- sys.exit(result)
+ sys.exit(cli())
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2014-10-07 19:17:27
|
Revision: 1083
http://sourceforge.net/p/cedar-backup/code/1083
Author: pronovic
Date: 2014-10-07 19:17:12 +0000 (Tue, 07 Oct 2014)
Log Message:
-----------
Start implementing new tool cback-amazons3-sync
Modified Paths:
--------------
cedar-backup2/trunk/CedarBackup2/tools/__init__.py
cedar-backup2/trunk/Changelog
cedar-backup2/trunk/MANIFEST.in
cedar-backup2/trunk/util/test.py
Added Paths:
-----------
cedar-backup2/trunk/CedarBackup2/tools/amazons3.py
cedar-backup2/trunk/doc/cback-amazons3-sync.1
cedar-backup2/trunk/testcase/synctests.py
cedar-backup2/trunk/util/cback-amazons3-sync
Modified: cedar-backup2/trunk/CedarBackup2/tools/__init__.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/tools/__init__.py 2014-10-07 19:15:10 UTC (rev 1082)
+++ cedar-backup2/trunk/CedarBackup2/tools/__init__.py 2014-10-07 19:17:12 UTC (rev 1083)
@@ -45,5 +45,5 @@
# Using 'from CedarBackup2.tools import *' will just import the modules listed
# in the __all__ variable.
-__all__ = [ 'span', ]
+__all__ = [ 'span', 'amazons3', ]
Added: cedar-backup2/trunk/CedarBackup2/tools/amazons3.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/tools/amazons3.py (rev 0)
+++ cedar-backup2/trunk/CedarBackup2/tools/amazons3.py 2014-10-07 19:17:12 UTC (rev 1083)
@@ -0,0 +1,978 @@
+# -*- coding: iso-8859-1 -*-
+# vim: set ft=python ts=3 sw=3 expandtab:
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+#
+# C E D A R
+# S O L U T I O N S "Software done right."
+# S O F T W A R E
+#
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+#
+# Copyright (c) 2014 Kenneth J. Pronovici.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License,
+# Version 2, as published by the Free Software Foundation.
+#
+# 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.
+#
+# Copies of the GNU General Public License are available from
+# the Free Software Foundation website, http://www.gnu.org/.
+#
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+#
+# Author : Kenneth J. Pronovici <pro...@ie...>
+# Language : Python (>= 2.5)
+# Project : Cedar Backup, release 2
+# Revision : $Id$
+# Purpose : Cedar Backup tool to synchronize an Amazon S3 bucket.
+#
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+########################################################################
+# Notes
+########################################################################
+
+"""
+Synchonizes a local directory with an Amazon S3 bucket.
+
+No configuration is required; all necessary information is taken from the
+command-line. The only thing configuration would help with is the path
+resolver interface, and it doesn't seem worth it to require configuration just
+to get that.
+
+@author: Kenneth J. Pronovici <pro...@ie...>
+"""
+
+########################################################################
+# Imported modules and constants
+########################################################################
+
+# System modules
+import sys
+import os
+import logging
+import getopt
+
+# Cedar Backup modules
+from CedarBackup2.release import AUTHOR, EMAIL, VERSION, DATE, COPYRIGHT
+from CedarBackup2.cli import setupLogging, DEFAULT_LOGFILE, DEFAULT_OWNERSHIP, DEFAULT_MODE
+from CedarBackup2.util import Diagnostics, splitCommandLine, encodePath
+
+
+########################################################################
+# Module-wide constants and variables
+########################################################################
+
+logger = logging.getLogger("CedarBackup2.log.tools.amazons3")
+
+SHORT_SWITCHES = "hVbql:o:m:OdsDv"
+LONG_SWITCHES = [ 'help', 'version', 'verbose', 'quiet',
+ 'logfile=', 'owner=', 'mode=',
+ 'output', 'debug', 'stack', 'diagnostics', "verifyOnly", ]
+
+
+#######################################################################
+# Options class
+#######################################################################
+
+class Options(object):
+
+ ######################
+ # Class documentation
+ ######################
+
+ """
+ Class representing command-line options for the cback-amazons3-sync script.
+
+ The C{Options} class is a Python object representation of the command-line
+ options of the cback script.
+
+ The object representation is two-way: a command line string or a list of
+ command line arguments can be used to create an C{Options} object, and then
+ changes to the object can be propogated back to a list of command-line
+ arguments or to a command-line string. An C{Options} object can even be
+ created from scratch programmatically (if you have a need for that).
+
+ There are two main levels of validation in the C{Options} class. The first
+ is field-level validation. Field-level validation comes into play when a
+ given field in an object is assigned to or updated. We use Python's
+ C{property} functionality to enforce specific validations on field values,
+ and in some places we even use customized list classes to enforce
+ validations on list members. You should expect to catch a C{ValueError}
+ exception when making assignments to fields if you are programmatically
+ filling an object.
+
+ The second level of validation is post-completion validation. Certain
+ validations don't make sense until an object representation of options is
+ fully "complete". We don't want these validations to apply all of the time,
+ because it would make building up a valid object from scratch a real pain.
+ For instance, we might have to do things in the right order to keep from
+ throwing exceptions, etc.
+
+ All of these post-completion validations are encapsulated in the
+ L{Options.validate} method. This method can be called at any time by a
+ client, and will always be called immediately after creating a C{Options}
+ object from a command line and before exporting a C{Options} object back to
+ a command line. This way, we get acceptable ease-of-use but we also don't
+ accept or emit invalid command lines.
+
+ @note: Lists within this class are "unordered" for equality comparisons.
+
+ @sort: __init__, __repr__, __str__, __cmp__
+ """
+
+ ##############
+ # Constructor
+ ##############
+
+ def __init__(self, argumentList=None, argumentString=None, validate=True):
+ """
+ Initializes an options object.
+
+ If you initialize the object without passing either C{argumentList} or
+ C{argumentString}, the object will be empty and will be invalid until it
+ is filled in properly.
+
+ No reference to the original arguments is saved off by this class. Once
+ the data has been parsed (successfully or not) this original information
+ is discarded.
+
+ The argument list is assumed to be a list of arguments, not including the
+ name of the command, something like C{sys.argv[1:]}. If you pass
+ C{sys.argv} instead, things are not going to work.
+
+ The argument string will be parsed into an argument list by the
+ L{util.splitCommandLine} function (see the documentation for that
+ function for some important notes about its limitations). There is an
+ assumption that the resulting list will be equivalent to C{sys.argv[1:]},
+ just like C{argumentList}.
+
+ Unless the C{validate} argument is C{False}, the L{Options.validate}
+ method will be called (with its default arguments) after successfully
+ parsing any passed-in command line. This validation ensures that
+ appropriate actions, etc. have been specified. Keep in mind that even if
+ C{validate} is C{False}, it might not be possible to parse the passed-in
+ command line, so an exception might still be raised.
+
+ @note: The command line format is specified by the L{_usage} function.
+ Call L{_usage} to see a usage statement for the cback script.
+
+ @note: It is strongly suggested that the C{validate} option always be set
+ to C{True} (the default) unless there is a specific need to read in
+ invalid command line arguments.
+
+ @param argumentList: Command line for a program.
+ @type argumentList: List of arguments, i.e. C{sys.argv}
+
+ @param argumentString: Command line for a program.
+ @type argumentString: String, i.e. "cback --verbose stage store"
+
+ @param validate: Validate the command line after parsing it.
+ @type validate: Boolean true/false.
+
+ @raise getopt.GetoptError: If the command-line arguments could not be parsed.
+ @raise ValueError: If the command-line arguments are invalid.
+ """
+ self._help = False
+ self._version = False
+ self._verbose = False
+ self._quiet = False
+ self._logfile = None
+ self._owner = None
+ self._mode = None
+ self._output = False
+ self._debug = False
+ self._stacktrace = False
+ self._diagnostics = False
+ self._verifyOnly = False
+ self._sourceDir = None
+ self._s3BucketUrl = None
+ if argumentList is not None and argumentString is not None:
+ raise ValueError("Use either argumentList or argumentString, but not both.")
+ if argumentString is not None:
+ argumentList = splitCommandLine(argumentString)
+ if argumentList is not None:
+ self._parseArgumentList(argumentList)
+ if validate:
+ self.validate()
+
+
+ #########################
+ # String representations
+ #########################
+
+ def __repr__(self):
+ """
+ Official string representation for class instance.
+ """
+ return self.buildArgumentString(validate=False)
+
+ def __str__(self):
+ """
+ Informal string representation for class instance.
+ """
+ return self.__repr__()
+
+
+ #############################
+ # Standard comparison method
+ #############################
+
+ def __cmp__(self, other):
+ """
+ Definition of equals operator for this class.
+ Lists within this class are "unordered" for equality comparisons.
+ @param other: Other object to compare to.
+ @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
+ """
+ if other is None:
+ return 1
+ if self.help != other.help:
+ if self.help < other.help:
+ return -1
+ else:
+ return 1
+ if self.version != other.version:
+ if self.version < other.version:
+ return -1
+ else:
+ return 1
+ if self.verbose != other.verbose:
+ if self.verbose < other.verbose:
+ return -1
+ else:
+ return 1
+ if self.quiet != other.quiet:
+ if self.quiet < other.quiet:
+ return -1
+ else:
+ return 1
+ if self.logfile != other.logfile:
+ if self.logfile < other.logfile:
+ return -1
+ else:
+ return 1
+ if self.owner != other.owner:
+ if self.owner < other.owner:
+ return -1
+ else:
+ return 1
+ if self.mode != other.mode:
+ if self.mode < other.mode:
+ return -1
+ else:
+ return 1
+ if self.output != other.output:
+ if self.output < other.output:
+ return -1
+ else:
+ return 1
+ if self.debug != other.debug:
+ if self.debug < other.debug:
+ return -1
+ else:
+ return 1
+ if self.stacktrace != other.stacktrace:
+ if self.stacktrace < other.stacktrace:
+ return -1
+ else:
+ return 1
+ if self.diagnostics != other.diagnostics:
+ if self.diagnostics < other.diagnostics:
+ return -1
+ else:
+ return 1
+ if self.verifyOnly != other.verifyOnly:
+ if self.verifyOnly < other.verifyOnly:
+ return -1
+ else:
+ return 1
+ if self.sourceDir != other.sourceDir:
+ if self.sourceDir < other.sourceDir:
+ return -1
+ else:
+ return 1
+ if self.s3BucketUrl != other.s3BucketUrl:
+ if self.s3BucketUrl < other.s3BucketUrl:
+ return -1
+ else:
+ return 1
+ return 0
+
+
+ #############
+ # Properties
+ #############
+
+ def _setHelp(self, value):
+ """
+ Property target used to set the help flag.
+ No validations, but we normalize the value to C{True} or C{False}.
+ """
+ if value:
+ self._help = True
+ else:
+ self._help = False
+
+ def _getHelp(self):
+ """
+ Property target used to get the help flag.
+ """
+ return self._help
+
+ def _setVersion(self, value):
+ """
+ Property target used to set the version flag.
+ No validations, but we normalize the value to C{True} or C{False}.
+ """
+ if value:
+ self._version = True
+ else:
+ self._version = False
+
+ def _getVersion(self):
+ """
+ Property target used to get the version flag.
+ """
+ return self._version
+
+ def _setVerbose(self, value):
+ """
+ Property target used to set the verbose flag.
+ No validations, but we normalize the value to C{True} or C{False}.
+ """
+ if value:
+ self._verbose = True
+ else:
+ self._verbose = False
+
+ def _getVerbose(self):
+ """
+ Property target used to get the verbose flag.
+ """
+ return self._verbose
+
+ def _setQuiet(self, value):
+ """
+ Property target used to set the quiet flag.
+ No validations, but we normalize the value to C{True} or C{False}.
+ """
+ if value:
+ self._quiet = True
+ else:
+ self._quiet = False
+
+ def _getQuiet(self):
+ """
+ Property target used to get the quiet flag.
+ """
+ return self._quiet
+
+ def _setLogfile(self, value):
+ """
+ Property target used to set the logfile parameter.
+ @raise ValueError: If the value cannot be encoded properly.
+ """
+ if value is not None:
+ if len(value) < 1:
+ raise ValueError("The logfile parameter must be a non-empty string.")
+ self._logfile = encodePath(value)
+
+ def _getLogfile(self):
+ """
+ Property target used to get the logfile parameter.
+ """
+ return self._logfile
+
+ def _setOwner(self, value):
+ """
+ Property target used to set the owner parameter.
+ If not C{None}, the owner must be a C{(user,group)} tuple or list.
+ Strings (and inherited children of strings) are explicitly disallowed.
+ The value will be normalized to a tuple.
+ @raise ValueError: If the value is not valid.
+ """
+ if value is None:
+ self._owner = None
+ else:
+ if isinstance(value, str):
+ raise ValueError("Must specify user and group tuple for owner parameter.")
+ if len(value) != 2:
+ raise ValueError("Must specify user and group tuple for owner parameter.")
+ if len(value[0]) < 1 or len(value[1]) < 1:
+ raise ValueError("User and group tuple values must be non-empty strings.")
+ self._owner = (value[0], value[1])
+
+ def _getOwner(self):
+ """
+ Property target used to get the owner parameter.
+ The parameter is a tuple of C{(user, group)}.
+ """
+ return self._owner
+
+ def _setMode(self, value):
+ """
+ Property target used to set the mode parameter.
+ """
+ if value is None:
+ self._mode = None
+ else:
+ try:
+ if isinstance(value, str):
+ value = int(value, 8)
+ else:
+ value = int(value)
+ except TypeError:
+ raise ValueError("Mode must be an octal integer >= 0, i.e. 644.")
+ if value < 0:
+ raise ValueError("Mode must be an octal integer >= 0. i.e. 644.")
+ self._mode = value
+
+ def _getMode(self):
+ """
+ Property target used to get the mode parameter.
+ """
+ return self._mode
+
+ def _setOutput(self, value):
+ """
+ Property target used to set the output flag.
+ No validations, but we normalize the value to C{True} or C{False}.
+ """
+ if value:
+ self._output = True
+ else:
+ self._output = False
+
+ def _getOutput(self):
+ """
+ Property target used to get the output flag.
+ """
+ return self._output
+
+ def _setDebug(self, value):
+ """
+ Property target used to set the debug flag.
+ No validations, but we normalize the value to C{True} or C{False}.
+ """
+ if value:
+ self._debug = True
+ else:
+ self._debug = False
+
+ def _getDebug(self):
+ """
+ Property target used to get the debug flag.
+ """
+ return self._debug
+
+ def _setStacktrace(self, value):
+ """
+ Property target used to set the stacktrace flag.
+ No validations, but we normalize the value to C{True} or C{False}.
+ """
+ if value:
+ self._stacktrace = True
+ else:
+ self._stacktrace = False
+
+ def _getStacktrace(self):
+ """
+ Property target used to get the stacktrace flag.
+ """
+ return self._stacktrace
+
+ def _setDiagnostics(self, value):
+ """
+ Property target used to set the diagnostics flag.
+ No validations, but we normalize the value to C{True} or C{False}.
+ """
+ if value:
+ self._diagnostics = True
+ else:
+ self._diagnostics = False
+
+ def _getDiagnostics(self):
+ """
+ Property target used to get the diagnostics flag.
+ """
+ return self._diagnostics
+
+ def _setVerifyOnly(self, value):
+ """
+ Property target used to set the verifyOnly flag.
+ No validations, but we normalize the value to C{True} or C{False}.
+ """
+ if value:
+ self._verifyOnly = True
+ else:
+ self._verifyOnly = False
+
+ def _getVerifyOnly(self):
+ """
+ Property target used to get the verifyOnly flag.
+ """
+ return self._verifyOnly
+
+ def _setSourceDir(self, value):
+ """
+ Property target used to set the sourceDir parameter.
+ """
+ if value is not None:
+ if len(value) < 1:
+ raise ValueError("The sourceDir parameter must be a non-empty string.")
+ self._sourceDir = value
+
+ def _getSourceDir(self):
+ """
+ Property target used to get the sourceDir parameter.
+ """
+ return self._sourceDir
+
+ def _setS3BucketUrl(self, value):
+ """
+ Property target used to set the s3BucketUrl parameter.
+ """
+ if value is not None:
+ if len(value) < 1:
+ raise ValueError("The s3BucketUrl parameter must be a non-empty string.")
+ self._s3BucketUrl = value
+
+ def _getS3BucketUrl(self):
+ """
+ Property target used to get the s3BucketUrl parameter.
+ """
+ return self._s3BucketUrl
+
+ help = property(_getHelp, _setHelp, None, "Command-line help (C{-h,--help}) flag.")
+ version = property(_getVersion, _setVersion, None, "Command-line version (C{-V,--version}) flag.")
+ verbose = property(_getVerbose, _setVerbose, None, "Command-line verbose (C{-b,--verbose}) flag.")
+ quiet = property(_getQuiet, _setQuiet, None, "Command-line quiet (C{-q,--quiet}) flag.")
+ logfile = property(_getLogfile, _setLogfile, None, "Command-line logfile (C{-l,--logfile}) parameter.")
+ owner = property(_getOwner, _setOwner, None, "Command-line owner (C{-o,--owner}) parameter, as tuple C{(user,group)}.")
+ mode = property(_getMode, _setMode, None, "Command-line mode (C{-m,--mode}) parameter.")
+ output = property(_getOutput, _setOutput, None, "Command-line output (C{-O,--output}) flag.")
+ debug = property(_getDebug, _setDebug, None, "Command-line debug (C{-d,--debug}) flag.")
+ stacktrace = property(_getStacktrace, _setStacktrace, None, "Command-line stacktrace (C{-s,--stack}) flag.")
+ diagnostics = property(_getDiagnostics, _setDiagnostics, None, "Command-line diagnostics (C{-D,--diagnostics}) flag.")
+ verifyOnly = property(_getVerifyOnly, _setVerifyOnly, None, "Command-line verifyOnly (C{-v,--verifyOnly}) flag.")
+ sourceDir = property(_getSourceDir, _setSourceDir, None, "Command-line sourceDir, source of sync.")
+ s3BucketUrl = property(_getS3BucketUrl, _setS3BucketUrl, None, "Command-line s3BucketUrl, target of sync.")
+
+
+ ##################
+ # Utility methods
+ ##################
+
+ def validate(self):
+ """
+ Validates command-line options represented by the object.
+
+ Unless C{--help} or C{--version} are supplied, at least one action must
+ be specified. Other validations (as for allowed values for particular
+ options) will be taken care of at assignment time by the properties
+ functionality.
+
+ @note: The command line format is specified by the L{_usage} function.
+ Call L{_usage} to see a usage statement for the cback script.
+
+ @raise ValueError: If one of the validations fails.
+ """
+ if not self.help and not self.version and not self.diagnostics:
+ if self.sourceDir is None or self.s3BucketUrl is None:
+ raise ValueError("Source directory and S3 bucket URL are both required.")
+
+ def buildArgumentList(self, validate=True):
+ """
+ Extracts options into a list of command line arguments.
+
+ The original order of the various arguments (if, indeed, the object was
+ initialized with a command-line) is not preserved in this generated
+ argument list. Besides that, the argument list is normalized to use the
+ long option names (i.e. --version rather than -V). The resulting list
+ will be suitable for passing back to the constructor in the
+ C{argumentList} parameter. Unlike L{buildArgumentString}, string
+ arguments are not quoted here, because there is no need for it.
+
+ Unless the C{validate} parameter is C{False}, the L{Options.validate}
+ method will be called (with its default arguments) against the
+ options before extracting the command line. If the options are not valid,
+ then an argument list will not be extracted.
+
+ @note: It is strongly suggested that the C{validate} option always be set
+ to C{True} (the default) unless there is a specific need to extract an
+ invalid command line.
+
+ @param validate: Validate the options before extracting the command line.
+ @type validate: Boolean true/false.
+
+ @return: List representation of command-line arguments.
+ @raise ValueError: If options within the object are invalid.
+ """
+ if validate:
+ self.validate()
+ argumentList = []
+ if self._help:
+ argumentList.append("--help")
+ if self.version:
+ argumentList.append("--version")
+ if self.verbose:
+ argumentList.append("--verbose")
+ if self.quiet:
+ argumentList.append("--quiet")
+ if self.logfile is not None:
+ argumentList.append("--logfile")
+ argumentList.append(self.logfile)
+ if self.owner is not None:
+ argumentList.append("--owner")
+ argumentList.append("%s:%s" % (self.owner[0], self.owner[1]))
+ if self.mode is not None:
+ argumentList.append("--mode")
+ argumentList.append("%o" % self.mode)
+ if self.output:
+ argumentList.append("--output")
+ if self.debug:
+ argumentList.append("--debug")
+ if self.stacktrace:
+ argumentList.append("--stack")
+ if self.diagnostics:
+ argumentList.append("--diagnostics")
+ if self.verifyOnly:
+ argumentList.append("--verifyOnly")
+ if self.sourceDir is not None:
+ argumentList.append(self.sourceDir)
+ if self.s3BucketUrl is not None:
+ argumentList.append(self.s3BucketUrl)
+ return argumentList
+
+ def buildArgumentString(self, validate=True):
+ """
+ Extracts options into a string of command-line arguments.
+
+ The original order of the various arguments (if, indeed, the object was
+ initialized with a command-line) is not preserved in this generated
+ argument string. Besides that, the argument string is normalized to use
+ the long option names (i.e. --version rather than -V) and to quote all
+ string arguments with double quotes (C{"}). The resulting string will be
+ suitable for passing back to the constructor in the C{argumentString}
+ parameter.
+
+ Unless the C{validate} parameter is C{False}, the L{Options.validate}
+ method will be called (with its default arguments) against the options
+ before extracting the command line. If the options are not valid, then
+ an argument string will not be extracted.
+
+ @note: It is strongly suggested that the C{validate} option always be set
+ to C{True} (the default) unless there is a specific need to extract an
+ invalid command line.
+
+ @param validate: Validate the options before extracting the command line.
+ @type validate: Boolean true/false.
+
+ @return: String representation of command-line arguments.
+ @raise ValueError: If options within the object are invalid.
+ """
+ if validate:
+ self.validate()
+ argumentString = ""
+ if self._help:
+ argumentString += "--help "
+ if self.version:
+ argumentString += "--version "
+ if self.verbose:
+ argumentString += "--verbose "
+ if self.quiet:
+ argumentString += "--quiet "
+ if self.logfile is not None:
+ argumentString += "--logfile \"%s\" " % self.logfile
+ if self.owner is not None:
+ argumentString += "--owner \"%s:%s\" " % (self.owner[0], self.owner[1])
+ if self.mode is not None:
+ argumentString += "--mode %o " % self.mode
+ if self.output:
+ argumentString += "--output "
+ if self.debug:
+ argumentString += "--debug "
+ if self.stacktrace:
+ argumentString += "--stack "
+ if self.diagnostics:
+ argumentString += "--diagnostics "
+ if self.verifyOnly:
+ argumentString += "--verifyOnly "
+ if self.sourceDir is not None:
+ argumentString += "\"%s\" " % self.sourceDir
+ if self.s3BucketUrl is not None:
+ argumentString += "\"%s\" " % self.s3BucketUrl
+ return argumentString
+
+ def _parseArgumentList(self, argumentList):
+ """
+ Internal method to parse a list of command-line arguments.
+
+ Most of the validation we do here has to do with whether the arguments
+ can be parsed and whether any values which exist are valid. We don't do
+ any validation as to whether required elements exist or whether elements
+ exist in the proper combination (instead, that's the job of the
+ L{validate} method).
+
+ For any of the options which supply parameters, if the option is
+ duplicated with long and short switches (i.e. C{-l} and a C{--logfile})
+ then the long switch is used. If the same option is duplicated with the
+ same switch (long or short), then the last entry on the command line is
+ used.
+
+ @param argumentList: List of arguments to a command.
+ @type argumentList: List of arguments to a command, i.e. C{sys.argv[1:]}
+
+ @raise ValueError: If the argument list cannot be successfully parsed.
+ """
+ switches = { }
+ opts, remaining = getopt.getopt(argumentList, SHORT_SWITCHES, LONG_SWITCHES)
+ for o, a in opts: # push the switches into a hash
+ switches[o] = a
+ if switches.has_key("-h") or switches.has_key("--help"):
+ self.help = True
+ if switches.has_key("-V") or switches.has_key("--version"):
+ self.version = True
+ if switches.has_key("-b") or switches.has_key("--verbose"):
+ self.verbose = True
+ if switches.has_key("-q") or switches.has_key("--quiet"):
+ self.quiet = True
+ if switches.has_key("-l"):
+ self.logfile = switches["-l"]
+ if switches.has_key("--logfile"):
+ self.logfile = switches["--logfile"]
+ if switches.has_key("-o"):
+ self.owner = switches["-o"].split(":", 1)
+ if switches.has_key("--owner"):
+ self.owner = switches["--owner"].split(":", 1)
+ if switches.has_key("-m"):
+ self.mode = switches["-m"]
+ if switches.has_key("--mode"):
+ self.mode = switches["--mode"]
+ if switches.has_key("-O") or switches.has_key("--output"):
+ self.output = True
+ if switches.has_key("-d") or switches.has_key("--debug"):
+ self.debug = True
+ if switches.has_key("-s") or switches.has_key("--stack"):
+ self.stacktrace = True
+ if switches.has_key("-D") or switches.has_key("--diagnostics"):
+ self.diagnostics = True
+ if switches.has_key("-v") or switches.has_key("--verifyOnly"):
+ self.verifyOnly = True
+ try:
+ (self.sourceDir, self.s3BucketUrl) = remaining
+ except ValueError:
+ pass
+
+
+#######################################################################
+# Public functions
+#######################################################################
+
+#################
+# cli() function
+#################
+
+def cli():
+ """
+ Implements the command-line interface for the C{cback-amazons3-sync} script.
+
+ Essentially, this is the "main routine" for the cback-amazons3-sync script. It does
+ all of the argument processing for the script, and then also implements the
+ tool functionality.
+
+ This function looks pretty similiar to C{CedarBackup2.cli.cli()}. It's not
+ easy to refactor this code to make it reusable and also readable, so I've
+ decided to just live with the duplication.
+
+ A different error code is returned for each type of failure:
+
+ - C{1}: The Python interpreter version is < 2.5
+ - C{2}: Error processing command-line arguments
+ - C{3}: Error configuring logging
+ - C{5}: Backup was interrupted with a CTRL-C or similar
+ - C{6}: Error executing other parts of the script
+
+ @note: This script uses print rather than logging to the INFO level, because
+ it is interactive. Underlying Cedar Backup functionality uses the logging
+ mechanism exclusively.
+
+ @return: Error code as described above.
+ """
+ try:
+ if map(int, [sys.version_info[0], sys.version_info[1]]) < [2, 5]:
+ sys.stderr.write("Python version 2.5 or greater required.\n")
+ return 1
+ except:
+ # sys.version_info isn't available before 2.0
+ sys.stderr.write("Python version 2.5 or greater required.\n")
+ return 1
+
+ try:
+ options = Options(argumentList=sys.argv[1:])
+ except Exception, e:
+ _usage()
+ sys.stderr.write(" *** Error: %s\n" % e)
+ return 2
+
+ if options.help:
+ _usage()
+ return 0
+ if options.version:
+ _version()
+ return 0
+ if options.diagnostics:
+ _diagnostics()
+ return 0
+
+ try:
+ logfile = setupLogging(options)
+ except Exception, e:
+ sys.stderr.write("Error setting up logging: %s\n" % e)
+ return 3
+
+ logger.info("Cedar Backup Amazon S3 sync run started.")
+ logger.info("Options were [%s]" % options)
+ logger.info("Logfile is [%s]" % logfile)
+
+ if options.stacktrace:
+ _executeAction(options)
+ else:
+ try:
+ _executeAction(options)
+ except KeyboardInterrupt:
+ logger.error("Backup interrupted.")
+ logger.info("Cedar Backup Amazon S3 sync run completed with status 5.")
+ return 5
+ except Exception, e:
+ logger.error("Error executing backup: %s" % e)
+ logger.info("Cedar Backup Amazon S3 sync run completed with status 6.")
+ return 6
+
+ logger.info("Cedar Backup Amazon S3 sync run completed with status 0.")
+ return 0
+
+
+#######################################################################
+# Utility functions
+#######################################################################
+
+####################
+# _usage() function
+####################
+
+def _usage(fd=sys.stderr):
+ """
+ Prints usage information for the cback-amazons3-sync script.
+ @param fd: File descriptor used to print information.
+ @note: The C{fd} is used rather than C{print} to facilitate unit testing.
+ """
+ fd.write("\n")
+ fd.write(" Usage: cback-amazons3-sync [switches] sourceDir s3bucketUrl\n")
+ fd.write("\n")
+ fd.write(" Cedar Backup Amazon S3 sync tool.\n")
+ fd.write("\n")
+ fd.write(" This Cedar Backup utility synchronizes a local directory to an Amazon S3\n")
+ fd.write(" bucket. After the sync is complete, a validation step is takane. An\n")
+ fd.write(" error is reported if the contents of the bucket do not match \n")
+ fd.write(" the source directory, or if the indicated size for any file differs.\n")
+ fd.write(" This tool is a wrapper over the AWS CLI command-line tool.\n")
+ fd.write("\n")
+ fd.write(" The following arguments are required:\n")
+ fd.write("\n")
+ fd.write(" sourceDir The local source directory on disk (must exist)\n")
+ fd.write(" s3BucketUrl The URL to the target Amazon S3 bucket\n")
+ fd.write("\n")
+ fd.write(" The following switches are accepted:\n")
+ fd.write("\n")
+ fd.write(" -h, --help Display this usage/help listing\n")
+ fd.write(" -V, --version Display version information\n")
+ fd.write(" -b, --verbose Print verbose output as well as logging to disk\n")
+ fd.write(" -q, --quiet Run quietly (display no output to the screen)\n")
+ fd.write(" -l, --logfile Path to logfile (default: %s)\n" % DEFAULT_LOGFILE)
+ fd.write(" -o, --owner Logfile ownership, user:group (default: %s:%s)\n" % (DEFAULT_OWNERSHIP[0], DEFAULT_OWNERSHIP[1]))
+ fd.write(" -m, --mode Octal logfile permissions mode (default: %o)\n" % DEFAULT_MODE)
+ fd.write(" -O, --output Record some sub-command (i.e. aws) output to the log\n")
+ fd.write(" -d, --debug Write debugging information to the log (implies --output)\n")
+ fd.write(" -s, --stack Dump a Python stack trace instead of swallowing exceptions\n") # exactly 80 characters in width!
+ fd.write(" -D, --diagnostics Print runtime diagnostics to the screen and exit\n")
+ fd.write(" -v, --verifyOnly Only verify the S3 bucket contents, do not make changes\n")
+ fd.write("\n")
+ fd.write(" Typical usage would be something like:\n")
+ fd.write("\n")
+ fd.write(" cback-amazons3-sync /home/myuser/subdir s3://example.com-backup/myuser\n")
+ fd.write("\n")
+ fd.write(" This will sync the contents of /home/myuser/subdir into the indiated bucket.\n")
+ fd.write("\n")
+
+
+######################
+# _version() function
+######################
+
+def _version(fd=sys.stdout):
+ """
+ Prints version information for the cback script.
+ @param fd: File descriptor used to print information.
+ @note: The C{fd} is used rather than C{print} to facilitate unit testing.
+ """
+ fd.write("\n")
+ fd.write(" Cedar Backup Amazon S3 sync tool.\n")
+ fd.write(" Included with Cedar Backup version %s, released %s.\n" % (VERSION, DATE))
+ fd.write("\n")
+ fd.write(" Copyright (c) %s %s <%s>.\n" % (COPYRIGHT, AUTHOR, EMAIL))
+ fd.write(" See CREDITS for a list of included code and other contributors.\n")
+ fd.write(" This is free software; there is NO warranty. See the\n")
+ fd.write(" GNU General Public License version 2 for copying conditions.\n")
+ fd.write("\n")
+ fd.write(" Use the --help option for usage information.\n")
+ fd.write("\n")
+
+
+##########################
+# _diagnostics() function
+##########################
+
+def _diagnostics(fd=sys.stdout):
+ """
+ Prints runtime diagnostics information.
+ @param fd: File descriptor used to print information.
+ @note: The C{fd} is used rather than C{print} to facilitate unit testing.
+ """
+ fd.write("\n")
+ fd.write("Diagnostics:\n")
+ fd.write("\n")
+ Diagnostics().printDiagnostics(fd=fd, prefix=" ")
+ fd.write("\n")
+
+
+############################
+# _executeAction() function
+############################
+
+def _executeAction(options):
+ """
+ Implements the guts of the cback-amazons3-sync tool.
+
+ @param options: Program command-line options.
+ @type options: Options object.
+
+ @raise Exception: Under many generic error conditions
+ """
+ if not os.path.isdir(options.sourceDir):
+ raise Exception("Source directory does not exist on disk.")
+
+
+#########################################################################
+# Main routine
+########################################################################
+
+if __name__ == "__main__":
+ result = cli()
+ sys.exit(result)
+
Property changes on: cedar-backup2/trunk/CedarBackup2/tools/amazons3.py
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Modified: cedar-backup2/trunk/Changelog
===================================================================
--- cedar-backup2/trunk/Changelog 2014-10-07 19:15:10 UTC (rev 1082)
+++ cedar-backup2/trunk/Changelog 2014-10-07 19:17:12 UTC (rev 1083)
@@ -1,5 +1,6 @@
Version 2.23.4 unreleased
+ * Implement a new tool called cback-amazons3-sync.
* Add support for missing --diagnostics flag in cback-span script.
Version 2.23.3 03 Oct 2014
Modified: cedar-backup2/trunk/MANIFEST.in
===================================================================
--- cedar-backup2/trunk/MANIFEST.in 2014-10-07 19:15:10 UTC (rev 1082)
+++ cedar-backup2/trunk/MANIFEST.in 2014-10-07 19:17:12 UTC (rev 1083)
@@ -11,6 +11,7 @@
include CedarBackup2/tools/*.py
include CedarBackup2/writers/*.py
include util/cback-span
+include util/cback-amazons3-sync
include util/test.py
include util/knapsackdemo.py
include util/docbook/*
@@ -21,6 +22,7 @@
include manual/src/images/html/*.png
include doc/cback.1
include doc/cback-span.1
+include doc/cback-amazons3-sync.1
include doc/cback.conf.sample
include doc/docbook.txt
include doc/release.txt
Added: cedar-backup2/trunk/doc/cback-amazons3-sync.1
===================================================================
--- cedar-backup2/trunk/doc/cback-amazons3-sync.1 (rev 0)
+++ cedar-backup2/trunk/doc/cback-amazons3-sync.1 2014-10-07 19:17:12 UTC (rev 1083)
@@ -0,0 +1,141 @@
+.\" vim: set ft=nroff .\"
+.\" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+.\" #
+.\" # C E D A R
+.\" # S O L U T I O N S "Software done right."
+.\" # S O F T W A R E
+.\" #
+.\" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+.\" #
+.\" # Author : Kenneth J. Pronovici <pro...@ie...>
+.\" # Language : nroff
+.\" # Project : Cedar Backup, release 2
+.\" # Revision : $Id: cback-span.1 1011 2010-07-10 23:58:29Z pronovic $
+.\" # Purpose : Manpage for cback-span script
+.\" #
+.\" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+.\"
+.TH cback\-amazons3-sync "1" "Oct 2014" "Cedar Backup" "Kenneth J. Pronovici"
+.SH NAME
+cback\-amazons3-sync \- Synchronize a local directory with an Amazon S3 bucket
+.SH SYNOPSIS
+.B cback\-amazons3-sync
+[\fIswitches\fR]
+sourceDir s3BucketUrl
+.SH DESCRIPTION
+.PP
+This is the Cedar Backup Amazon S3 sync tool. It synchronizes a local
+directory to an Amazon S3 cloud storage bucket. After the sync is complete, a
+validation step is taken. An error is reported if the contents of the bucket
+do not match the source directory, or if the indicated size for any file
+differs.
+.PP
+Generally, one can run the cback\-amazons3-sync command with no special
+switches. This will start it using the default Cedar Backup log file, etc.
+You only need to use the switches if you need to change the default behavior.
+.SH ARGUMENTS
+.TP
+\fBsourceDir\fR
+The source directory on a local disk.
+.TP
+\fBs3BucketUrl\fR
+The URL specifying the location of the Amazon S3 cloud storage bucket
+to synchronize with, like s3://example.com-backup/subdir.
+.SH SWITCHES
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display usage/help listing.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Display version information.
+.TP
+\fB\-b\fR, \fB\-\-verbose\fR
+Print verbose output to the screen as well writing to the logfile. When this
+option is enabled, most information that would normally be written to the
+logfile will also be written to the screen.
+.TP
+\fB\-l\fR, \fB\-\-logfile\fR
+Specify the path to an alternate logfile. The default logfile file is
+/var/log/cback.log.
+.TP
+\fB\-o\fR, \fB\-\-owner\fR
+Specify the ownership of the logfile, in the form user:group. The default
+ownership is root:adm, to match the Debian standard for most logfiles. This
+value will only be used when creating a new logfile. If the logfile already
+exists when the cback script is executed, it will retain its existing ownership
+and mode. Only user and group names may be used, not numeric uid and gid
+values.
+.TP
+\fB\-m\fR, \fB\-\-mode\fR
+Specify the permissions for the logfile, using the numeric mode as in chmod(1).
+The default mode is 640 (\-rw\-r\-\-\-\-\-). This value will only be used when
+creating a new logfile. If the logfile already exists when the cback script is
+executed, it will retain its existing ownership and mode.
+.TP
+\fB\-O\fR, \fB\-\-output\fR
+Record some sub-command output to the logfile. When this option is enabled, all
+output from system commands will be logged. This might be useful for debugging
+or just for reference.
+.TP
+\fB\-d\fR, \fB\-\-debug\fR
+Write debugging information to the logfile. This option produces a high volume
+of output, and would generally only be needed when debugging a problem. This
+option implies the \-\-output option, as well.
+.TP
+\fB\-s\fR, \fB\-\-stack\fR
+Dump a Python stack trace instead of swallowing exceptions. This forces Cedar
+Backup to dump the entire Python stack trace associated with an error, rather
+than just progating last message it received back up to the user interface.
+Under some circumstances, this is useful information to include along with a
+bug report.
+.TP
+\fB\-D\fR, \fB\-\-diagnostics\fR
+Display runtime diagnostic information and then exit. This diagnostic
+information is often useful when filing a bug report.
+.SH RETURN VALUES
+.PP
+This command returns 0 (zero) upon normal completion, and several other error
+codes related to particular errors.
+.TP
+\fB1\fR
+The Python interpreter version is < 2.5.
+.TP
+\fB2\fR
+Error processing command\-line arguments.
+.TP
+\fB3\fR
+Error configuring logging.
+.TP
+\fB5\fR
+Backup was interrupted with a CTRL\-C or similar.
+.TP
+\fB6\fR
+Other error during processing.
+.SH NOTES
+.PP
+This tool is a wrapper over the Amazon AWS CLI interface found in the aws(1)
+command.
+.PP
+Cedar Backup itself is designed to run as root. However, this command can be
+run safely as any user that is configured to use the Amazon AWS CLI interface.
+The aws(1) command will be executed by the same user which is executing the
+cback-amazons3-sync.
+.PP
+You must configure the AWS CLI interface to have a valid connection to Amazon
+S3 infrastructure before using this command. For more information about how to
+accomplish this, see the Cedar Backup user guide.
+.SH SEE ALSO
+cback(1)
+.SH FILES
+.TP
+\fI/var/log/cback.log\fR - Default log file
+.SH BUGS
+Report bugs to <support@cedar\-solutions.com>.
+.SH AUTHOR
+Written by Kenneth J. Pronovici <pro...@ie...>.
+.SH COPYRIGHT
+Copyright (c) 2014 Kenneth J. Pronovici.
+.br
+This is free software; see the source for copying conditions. There is
+NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
Added: cedar-backup2/trunk/testcase/synctests.py
===================================================================
--- cedar-backup2/trunk/testcase/synctests.py (rev 0)
+++ cedar-backup2/trunk/testcase/synctests.py 2014-10-07 19:17:12 UTC (rev 1083)
@@ -0,0 +1,3304 @@
+#!/usr/bin/env python
+# -*- coding: iso-8859-1 -*-
+# vim: set ft=python ts=3 sw=3 expandtab:
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+#
+# C E D A R
+# S O L U T I O N S "Software done right."
+# S O F T W A R E
+#
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+#
+# Copyright (c) 2007,2010 Kenneth J. Pronovici.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License,
+# Version 2, as published by the Free Software Foundation.
+#
+# 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.
+#
+# Copies of the GNU General Public License are available from
+# the Free Software Foundation website, http://www.gnu.org/.
+#
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+#
+# Author : Kenneth J. Pronovici <pro...@ie...>
+# Language : Python (>= 2.5)
+# Project : Cedar Backup, release 2
+# Revision : $Id$
+# Purpose : Tests Amazon S3 sync tool functionality.
+#
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+########################################################################
+# Module documentation
+########################################################################
+
+"""
+Unit tests for CedarBackup2/tools/amazons3.py.
+
+Code Coverage
+=============
+
+ This module contains individual tests for the many of the public functions
+ and classes implemented in tools/amazons3.py. Where possible, we test
+ functions that print output by passing a custom file descriptor. Sometimes,
+ we only ensure that a function or method runs without failure, and we don't
+ validate what its result is or what it prints out.
+
+Naming Conventions
+==================
+
+ I prefer to avoid large unit tests which validate more than one piece of
+ functionality, and I prefer to avoid using overly descriptive (read: long)
+ test names, as well. Instead, I use lots of very small tests that each
+ validate one specific thing. These small tests are then named with an index
+ number, yielding something like C{testAddDir_001} or C{testValidate_010}.
+ Each method has a docstring describing what it's supposed to accomplish. I
+ feel that this makes it easier to judge how important a given failure is,
+ and also makes it somewhat easier to diagnose and fix individual problems.
+
+Full vs. Reduced Tests
+======================
+
+ All of the tests in this module are considered safe to be run in an average
+ build environment. There is a no need to use a SYNCTESTS_FULL environment
+ variable to provide a "reduced feature set" test suite as for some of the
+ other test modules.
+
+@author Kenneth J. Pronovici <pro...@ie...>
+"""
+
+
+########################################################################
+# Import modules and do runtime validations
+########################################################################
+
+import unittest
+from getopt import GetoptError
+from CedarBackup2.testutil import failUnlessAssignRaises, captureOutput
+from CedarBackup2.tools.amazons3 import _usage, _version
+from CedarBackup2.tools.amazons3 import Options
+
+
+#######################################################################
+# Test Case Classes
+#######################################################################
+
+######################
+# TestFunctions class
+######################
+
+class TestFunctions(unittest.TestCase):
+
+ """Tests for the public functions."""
+
+ ################
+ # Setup methods
+ ################
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+
+ ########################
+ # Test simple functions
+ ########################
+
+ def testSimpleFuncs_001(self):
+ """
+ Test that the _usage() function runs without errors.
+ We don't care what the output is, and we don't check.
+ """
+ captureOutput(_usage)
+
+ def testSimpleFuncs_002(self):
+ """
+ Test that the _version() function runs without errors.
+ We don't care what the output is, and we don't check.
+ """
+ captureOutput(_version)
+
+
+####################
+# TestOptions class
+####################
+
+class TestOptions(unittest.TestCase):
+
+ """Tests for the Options class."""
+
+ ################
+ # Setup methods
+ ################
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+
+ ##################
+ # Utility methods
+ ##################
+
+ def failUnlessAssignRaises(self, exception, obj, prop, value):
+ """Equivalent of L{failUnlessRaises}, but used for property assignments instead."""
+ failUnlessAssignRaises(self, exception, obj, prop, value)
+
+
+ ############################
+ # Test __repr__ and __str__
+ ############################
+
+ def testStringFuncs_001(self):
+ """
+ Just make sure that the string functions don't have errors (i.e. bad variable names).
+ """
+ obj = Options()
+ obj.__repr__()
+ obj.__str__()
+
+
+ ##################################
+ # Test constructor and attributes
+ ##################################
+
+ def testConstructor_001(self):
+ """
+ Test constructor with no arguments.
+ """
+ options = Options()
+ self.failUnlessEqual(False, options.help)
+ self.failUnlessEqual(False, options.version)
+ self.failUnlessEqual(False, options.verbose)
+ self.failUnlessEqual(False, options.quiet)
+ self.failUnlessEqual(None, options.logfile)
+ self.failUnlessEqual(None, options.owner)
+ self.failUnlessEqual(None, options.mode)
+ self.failUnlessEqual(False, options.output)
+ self.failUnlessEqual(False, options.debug)
+ self.failUnlessEqual(False, options.stacktrace)
+ self.failUnlessEqual(False, options.diagnostics)
+ self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(None, options.sourceDir)
+ self.failUnlessEqual(None, options.s3BucketUrl)
+
+ def testConstructor_002(self):
+ """
+ Test constructor with validate=False, no other arguments.
+ """
+ options = Options(validate=False)
+ self.failUnlessEqual(False, options.help)
+ self.failUnlessEqual(False, options.version)
+ self.failUnlessEqual(False, options.verbose)
+ self.failUnlessEqual(False, options.quiet)
+ self.failUnlessEqual(None, options.logfile)
+ self.failUnlessEqual(None, options.owner)
+ self.failUnlessEqual(None, options.mode)
+ self.failUnlessEqual(False, options.output)
+ self.failUnlessEqual(False, options.debug)
+ self.failUnlessEqual(False, options.stacktrace)
+ self.failUnlessEqual(False, options.diagnostics)
+ self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(None, options.sourceDir)
+ self.failUnlessEqual(None, options.s3BucketUrl)
+
+ def testConstructor_003(self):
+ """
+ Test constructor with argumentList=[], validate=False.
+ """
+ options = Options(argumentList=[], validate=False)
+ self.failUnlessEqual(False, options.help)
+ self.failUnlessEqual(False, options.version)
+ self.failUnlessEqual(False, options.verbose)
+ self.failUnlessEqual(False, options.quiet)
+ self.failUnlessEqual(None, options.logfile)
+ self.failUnlessEqual(None, options.owner)
+ self.failUnlessEqual(None, options.mode)
+ self.failUnlessEqual(False, options.output)
+ self.failUnlessEqual(False, options.debug)
+ self.failUnlessEqual(False, options.stacktrace)
+ self.failUnlessEqual(False, options.diagnostics)
+ self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(None, options.sourceDir)
+ self.failUnlessEqual(None, options.s3BucketUrl)
+
+ def testConstructor_004(self):
+ """
+ Test constructor with argumentString="", validate=False.
+ """
+ options = Options(argumentString="", validate=False)
+ self.failUnlessEqual(False, options.help)
+ self.failUnlessEqual(False, options.version)
+ self.failUnlessEqual(False, options.verbose)
+ self.failUnlessEqual(False, options.quiet)
+ self.failUnlessEqual(None, options.logfile)
+ self.failUnlessEqual(None, options.owner)
+ self.failUnlessEqual(None, options.mode)
+ self.failUnlessEqual(False, options.output)
+ self.failUnlessEqual(False, options.debug)
+ self.failUnlessEqual(False, options.stacktrace)
+ self.failUnlessEqual(False, options.diagnostics)
+ self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(None, options.sourceDir)
+ self.failUnlessEqual(None, options.s3BucketUrl)
+
+ def testConstructor_005(self):
+ """
+ Test constructor with argumentList=["--help", ], validate=False.
+ """
+ options = Options(argumentList=["--help", ], validate=False)
+ self.failUnlessEqual(True, options.help)
+ self.failUnlessEqual(False, options.version)
+ self.failUnlessEqual(False, options.verbose)
+ self.failUnlessEqual(False, options.quiet)
+ self.failUnlessEqual(None, options.logfile)
+ self.failUnlessEqual(None, options.owner)
+ self.failUnlessEqual(None, options.mode)
+ self.failUnlessEqual(False, options.output)
+ self.failUnlessEqual(False, options.debug)
+ self.failUnlessEqual(False, options.stacktrace)
+ self.failUnlessEqual(False, options.diagnostics)
+ self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(None, options.sourceDir)
+ self.failUnlessEqual(None, options.s3BucketUrl)
+
+ def testConstructor_006(self):
+ """
+ Test constructor with argumentString="--help", validate=False.
+ """
+ options = Options(argumentString="--help", validate=False)
+ self.failUnlessEqual(True, options.help)
+ self.failUnlessEqual(False, options.version)
+ self.failUnlessEqual(False, options.verbose)
+ self.failUnlessEqual(False, options.quiet)
+ self.failUnlessEqual(None, options.logfile)
+ self.failUnlessEqual(None, options.owner)
+ self.failUnlessEqual(None, options.mode)
+ self.failUnlessEqual(False, options.output)
+ self.failUnlessEqual(False, options.debug)
+ self.failUnlessEqual(False, options.stacktrace)
+ self.failUnlessEqual(False, options.diagnostics)
+ self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(None, options.sourceDir)
+ self.failUnlessEqual(None, options.s3BucketUrl)
+
+ def testConstructor_007(self):
+ """
+ Test constructor with argumentList=["-h", ], validate=False.
+ """
+ options = Options(argumentList=["-h", ], validate=False)
+ self.failUnlessEqual(True, options.help)
+ self.failUnlessEqual(False, options.version)
+ self.failUnlessEqual(False, options.verbose)
+ self.failUnlessEqual(False, options.quiet)
+ self.failUnlessEqual(None, options.logfile)
+ self.failUnlessEqual(None, options.owner)
+ self.failUnlessEqual(None, options.mode)
+ self.failUnlessEqual(False, options.output)
+ self.failUnlessEqual(False, options.debug)
+ self.failUnlessEqual(False, options.stacktrace)
+ self.failUnlessEqual(False, options.diagnostics)
+ self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(None, options.sourceDir)
+ self.failUnlessEqual(None, options.s3BucketUrl)
+
+ def testConstructor_008(self):
+ """
+ Test constructor with argumentString="-h", validate=False.
+ """
+ options = Options(argumentString="-h", validate=False)
+ self.failUnlessEqual(True, options.help)
+ self.failUnlessEqual(False, options.version)
+ self.failUnlessEqual(False, options.verbose)
+ self.failUnlessEqual(False, options.quiet)
+ self.failUnlessEqual(None, options.logfile)
+ self.failUnlessEqual(None, options.owner)
+ self.failUnlessEqual(None, options.mode)
+ self.failUnlessEqual(False, options.output)
+ self.failUnlessEqual(False, options.debug)
+ self.failUnlessEqual(False, options.stacktrace)
+ self.failUnlessEqual(False, options.diagnostics)
+ self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(None, options.sourceDir)
+ self.failUnlessEqual(None, options.s3BucketUrl)
+
+ def testConstructor_009(self):
+ """
+ Test constructor with argumentList=["--version", ], validate=False.
+ """
+ options = Options(argumentList=["--version", ], validate=False)
+ self.failUnlessEqual(False, options.help)
+ self.failUnlessEqual(True, options.version)
+ self.failUnlessEqual(False, options.verbose)
+ self.failUnlessEqual(False, options.quiet)
+ self.failUnlessEqual(None, options.logfile)
+ self.failUnlessEqual(None, options.owner)
+ self.failUnlessEqual(None, options.mode)
+ self.failUnlessEqual(False, options.output)
+ self.failUnlessEqual(False, options.debug)
+ self.failUnlessEqual(False, options.stacktrace)
+ self.failUnlessEqual(False, options.diagnostics)
+ self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(None, options.sourceDir)
+ self.failUnlessEqual(None, options.s3BucketUrl)
+
+ def testConstructor_010(self):
+ """
+ Test constructor with argumentString="--version", validate=False.
+ """
+ options = Options(argumentString="--version", validate=False)
+ self.failUnlessEqual(False, options.help)
+ self.failUnlessEqual(True, options.version)
+ self.failUnlessEqual(False, options.verbose)
+ self.failUnlessEqual(False, options.quiet)
+ self.failUnlessEqual(None, options.logfile)
+ self.failUnlessEqual(None, options.owner)
+ self.failUnlessEqual(None, options.mode)
+ self.failUnlessEqual(False, options.output)
+ self.failUnlessEqual(False, options.debug)
+ self.failUnlessEqual(False, options.stacktrace)
+ self.failUnlessEqual(False, options.diagnostics)
+ self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(None, options.sourceDir)
+ self.failUnlessEqual(None, options.s3BucketUrl)
+
+ def testConstructor_011(self):
+ """
+ Test constructor with argumentList=["-V", ], validate=False.
+ """
+ options = Options(argumentList=["-V", ], validate=False)
+ self.failUnlessEqual(False, options.help)
+ self.failUnlessEqual(True, options.version)
+ self.failUnlessEqual(False, options.verbose)
+ self.failUnlessEqual(False, options.quiet)
+ self.failUnlessEqual(None, options.logfile)
+ self.failUnlessEqual(None, options.owner)
+ self.failUnlessEqual(None, options.mode)
+ self.failUnlessEqual(False, options.output)
+ self.failUnlessEqual(False, options.debug)
+ self.failUnlessEqual(False, options.stacktrace)
+ self.failUnlessEqual(False, options.diagnostics)
+ self.failUnlessEqual(False, options.verifyOnly)
+ self.failUnlessEqual(None, options.sourceDir)
+ self.failUnlessEqual(None, options.s3BucketUrl)
+
+ def testConstructor_012(self):
+ """
+ Test constructor with argumentStri...
[truncated message content] |
|
From: <pro...@us...> - 2014-10-07 19:15:17
|
Revision: 1082
http://sourceforge.net/p/cedar-backup/code/1082
Author: pronovic
Date: 2014-10-07 19:15:10 +0000 (Tue, 07 Oct 2014)
Log Message:
-----------
Add support for missing --diagnostics flag in cback-span script
Modified Paths:
--------------
cedar-backup2/trunk/CedarBackup2/tools/span.py
cedar-backup2/trunk/Changelog
cedar-backup2/trunk/doc/cback-span.1
Modified: cedar-backup2/trunk/CedarBackup2/tools/span.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/tools/span.py 2014-10-07 19:13:18 UTC (rev 1081)
+++ cedar-backup2/trunk/CedarBackup2/tools/span.py 2014-10-07 19:15:10 UTC (rev 1082)
@@ -73,6 +73,7 @@
from CedarBackup2.actions.util import createWriter
from CedarBackup2.actions.store import writeIndicatorFile
from CedarBackup2.actions.util import findDailyDirs
+from CedarBackup2.util import Diagnostics
########################################################################
@@ -165,6 +166,9 @@
if options.version:
_version()
return 0
+ if options.diagnostics:
+ _diagnostics()
+ return 0
try:
logfile = setupLogging(options)
@@ -271,6 +275,23 @@
fd.write("\n")
+##########################
+# _diagnostics() function
+##########################
+
+def _diagnostics(fd=sys.stdout):
+ """
+ Prints runtime diagnostics information.
+ @param fd: File descriptor used to print information.
+ @note: The C{fd} is used rather than C{print} to facilitate unit testing.
+ """
+ fd.write("\n")
+ fd.write("Diagnostics:\n")
+ fd.write("\n")
+ Diagnostics().printDiagnostics(fd=fd, prefix=" ")
+ fd.write("\n")
+
+
############################
# _executeAction() function
############################
Modified: cedar-backup2/trunk/Changelog
===================================================================
--- cedar-backup2/trunk/Changelog 2014-10-07 19:13:18 UTC (rev 1081)
+++ cedar-backup2/trunk/Changelog 2014-10-07 19:15:10 UTC (rev 1082)
@@ -1,3 +1,7 @@
+Version 2.23.4 unreleased
+
+ * Add support for missing --diagnostics flag in cback-span script.
+
Version 2.23.3 03 Oct 2014
* Add new extension amazons3 as an optional replacement for the store action.
Modified: cedar-backup2/trunk/doc/cback-span.1
===================================================================
--- cedar-backup2/trunk/doc/cback-span.1 2014-10-07 19:13:18 UTC (rev 1081)
+++ cedar-backup2/trunk/doc/cback-span.1 2014-10-07 19:15:10 UTC (rev 1082)
@@ -15,7 +15,7 @@
.\" #
.\" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
.\"
-.TH cback\-span "1" "July 2010" "Cedar Backup" "Kenneth J. Pronovici"
+.TH cback\-span "1" "Oct 2014" "Cedar Backup" "Kenneth J. Pronovici"
.SH NAME
cback\-span \- Span staged data among multiple discs
.SH SYNOPSIS
@@ -87,6 +87,10 @@
than just progating last message it received back up to the user interface.
Under some circumstances, this is useful information to include along with a
bug report.
+.TP
+\fB\-D\fR, \fB\-\-diagnostics\fR
+Display runtime diagnostic information and then exit. This diagnostic
+information is often useful when filing a bug report.
.SH RETURN VALUES
.PP
This command returns 0 (zero) upon normal completion, and six other error
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2014-10-07 19:13:20
|
Revision: 1081
http://sourceforge.net/p/cedar-backup/code/1081
Author: pronovic
Date: 2014-10-07 19:13:18 +0000 (Tue, 07 Oct 2014)
Log Message:
-----------
Fix or ignore pylint warnings
Modified Paths:
--------------
cedar-backup2/trunk/testcase/filesystemtests.py
Modified: cedar-backup2/trunk/testcase/filesystemtests.py
===================================================================
--- cedar-backup2/trunk/testcase/filesystemtests.py 2014-10-07 18:20:20 UTC (rev 1080)
+++ cedar-backup2/trunk/testcase/filesystemtests.py 2014-10-07 19:13:18 UTC (rev 1081)
@@ -19381,6 +19381,7 @@
# Test _generateDigest()
#########################
+ # pylint: disable=E1101
def testGenerateDigest_001(self):
"""
Test that _generateDigest gives back same result as the slower simplistic
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2014-10-07 18:20:28
|
Revision: 1080
http://sourceforge.net/p/cedar-backup/code/1080
Author: pronovic
Date: 2014-10-07 18:20:20 +0000 (Tue, 07 Oct 2014)
Log Message:
-----------
Fix or ignore pylint warnings
Modified Paths:
--------------
cedar-backup2/trunk/CedarBackup2/filesystem.py
cedar-backup2/trunk/CedarBackup2/xmlutil.py
cedar-backup2/trunk/doc/procedure.txt
cedar-backup2/trunk/pylint-code.rc
cedar-backup2/trunk/pylint-test.rc
cedar-backup2/trunk/testcase/amazons3tests.py
Modified: cedar-backup2/trunk/CedarBackup2/filesystem.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/filesystem.py 2014-10-03 19:22:50 UTC (rev 1079)
+++ cedar-backup2/trunk/CedarBackup2/filesystem.py 2014-10-07 18:20:20 UTC (rev 1080)
@@ -911,7 +911,7 @@
@return: ASCII-safe SHA digest for the file.
@raise OSError: If the file cannot be opened.
"""
- # pylint: disable=C0103
+ # pylint: disable=C0103,E1101
try:
import hashlib
s = hashlib.sha1()
Modified: cedar-backup2/trunk/CedarBackup2/xmlutil.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/xmlutil.py 2014-10-03 19:22:50 UTC (rev 1079)
+++ cedar-backup2/trunk/CedarBackup2/xmlutil.py 2014-10-07 18:20:20 UTC (rev 1080)
@@ -58,7 +58,7 @@
@author: Kenneth J. Pronovici <pro...@ie...>
"""
-# pylint: disable=C0111,C0103,W0511,W0104
+# pylint: disable=C0111,C0103,W0511,W0104,W0106
########################################################################
# Imported modules
Modified: cedar-backup2/trunk/doc/procedure.txt
===================================================================
--- cedar-backup2/trunk/doc/procedure.txt 2014-10-03 19:22:50 UTC (rev 1079)
+++ cedar-backup2/trunk/doc/procedure.txt 2014-10-07 18:20:20 UTC (rev 1080)
@@ -4,7 +4,7 @@
- Make final update to Changelog
- Update CedarBackup2/release.py
- Run unit tests one last time (make test)
-- Run pychecker tests one last time (make check)
+- Run pychecker tests one last time (make check or make allcheck)
- Build the source distributions (make distrib)
- Run the util/release script for the right version
Modified: cedar-backup2/trunk/pylint-code.rc
===================================================================
--- cedar-backup2/trunk/pylint-code.rc 2014-10-03 19:22:50 UTC (rev 1079)
+++ cedar-backup2/trunk/pylint-code.rc 2014-10-07 18:20:20 UTC (rev 1080)
@@ -70,7 +70,7 @@
#enable-msg=
# Disable the message(s) with the given id(s).
-disable=I0011,W0702,W0703,W0704,C0302,C0321,R0902,R0911,R0912,R0913,R0914,R0915
+disable=I0011,W0702,W0703,W0704,C0302,C0321,R0902,R0911,R0912,R0913,R0914,R0915,R0801
[REPORTS]
Modified: cedar-backup2/trunk/pylint-test.rc
===================================================================
--- cedar-backup2/trunk/pylint-test.rc 2014-10-03 19:22:50 UTC (rev 1079)
+++ cedar-backup2/trunk/pylint-test.rc 2014-10-07 18:20:20 UTC (rev 1080)
@@ -73,7 +73,7 @@
#enable-msg=
# Disable the message(s) with the given id(s).
-disable=I0011,W0212,W0702,W0703,W0704,C0302,C0301,C0321,C0111,R0201,R0902,R0904,R0911,R0912,R0913,R0914,R0915
+disable=I0011,W0212,W0702,W0703,W0704,C0302,C0301,C0321,C0111,R0201,R0902,R0904,R0911,R0912,R0913,R0914,R0915,R0801
[REPORTS]
Modified: cedar-backup2/trunk/testcase/amazons3tests.py
===================================================================
--- cedar-backup2/trunk/testcase/amazons3tests.py 2014-10-03 19:22:50 UTC (rev 1079)
+++ cedar-backup2/trunk/testcase/amazons3tests.py 2014-10-07 18:20:20 UTC (rev 1080)
@@ -86,12 +86,9 @@
# System modules
import unittest
-import os
-import tempfile
# Cedar Backup modules
-from CedarBackup2.filesystem import FilesystemList
-from CedarBackup2.testutil import findResources, buildPath, removedir, extractTar, failUnlessAssignRaises, platformSupportsLinks
+from CedarBackup2.testutil import findResources, failUnlessAssignRaises
from CedarBackup2.xmlutil import createOutputDom, serializeDom
from CedarBackup2.extend.amazons3 import LocalConfig, AmazonS3Config
@@ -230,7 +227,7 @@
amazons3.encryptCommand = "encrypt"
self.failUnlessEqual("encrypt", amazons3.encryptCommand)
- def testConstructor_008(self):
+ def testConstructor_009(self):
"""
Test assignment of encryptCommand attribute, invalid value (empty).
"""
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2014-10-03 19:22:58
|
Revision: 1079
http://sourceforge.net/p/cedar-backup/code/1079
Author: pronovic
Date: 2014-10-03 19:22:50 +0000 (Fri, 03 Oct 2014)
Log Message:
-----------
Update the release procedure
Modified Paths:
--------------
cedar-backup2/trunk/doc/procedure.txt
Modified: cedar-backup2/trunk/doc/procedure.txt
===================================================================
--- cedar-backup2/trunk/doc/procedure.txt 2014-10-03 18:23:01 UTC (rev 1078)
+++ cedar-backup2/trunk/doc/procedure.txt 2014-10-03 19:22:50 UTC (rev 1079)
@@ -9,17 +9,18 @@
- Run the util/release script for the right version
- Copy source package to hcoop and install it
-- Copy source package to shell.sourceforge.net and install it
- Copy htmldocs.tar.gz to sourceforge and install it
-- FTP the source package to upload.sourceforge.net/incoming
-- Do a new file release at SourceForge
-- Put a new release announcement out on FreshMeat
-- Send a release email to cedar-backup-users
+- Copy the source package to daystrom's FTP directory
+- Sync daystrom's FTP directory structure with hcoop
+- Copy the orig file into the tarballs directory for stable and unstable
- Build the Debian package for unstable in a chroot
- Build the Debian package for stable in a chroot
- Push the latest Debian packages to daystrom
+- Upload the new packages to the Debian servers
- Sync daystrom's FTP directory structure with hcoop
-- Upload the new packages to the Debian servers
+- Do a new file release at SourceForge
+- Send a release email to cedar-backup-users
+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2014-10-03 18:23:04
|
Revision: 1078
http://sourceforge.net/p/cedar-backup/code/1078
Author: pronovic
Date: 2014-10-03 18:23:01 +0000 (Fri, 03 Oct 2014)
Log Message:
-----------
Tagging the 2.23.3 release of Cedar Backup.
Added Paths:
-----------
cedar-backup2/tags/CEDAR_BACKUP2_V2.23.3/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|