diff options
-rwxr-xr-x | be | 2 | ||||
-rw-r--r-- | becommands/comment.py | 10 | ||||
-rw-r--r-- | becommands/depend.py | 2 | ||||
-rw-r--r-- | becommands/tag.py | 2 | ||||
-rw-r--r-- | doc/be.1.sgml | 119 | ||||
-rw-r--r-- | libbe/arch.py | 4 | ||||
-rw-r--r-- | libbe/bug.py | 2 | ||||
-rw-r--r-- | libbe/bzr.py | 4 | ||||
-rw-r--r-- | libbe/cmdutil.py | 8 | ||||
-rw-r--r-- | libbe/comment.py | 22 | ||||
-rw-r--r-- | libbe/git.py | 4 | ||||
-rw-r--r-- | libbe/hg.py | 4 | ||||
-rw-r--r-- | libbe/rcs.py | 24 | ||||
-rwxr-xr-x | xml/be-xml-to-mbox | 11 |
14 files changed, 69 insertions, 149 deletions
@@ -27,7 +27,7 @@ if len(sys.argv) == 1 or sys.argv[1] in ('--help', '-h'): elif sys.argv[1] == '--complete': for command, module in cmdutil.iter_commands(): print command - print '\n'.join(["--help","--complete","--options"]) + print '\n'.join(["--help","--complete","--options","--version"]) elif sys.argv[1] == '--version': print _version.version_info["revision_id"] else: diff --git a/becommands/comment.py b/becommands/comment.py index f7459dd..b31a6e7 100644 --- a/becommands/comment.py +++ b/becommands/comment.py @@ -93,9 +93,13 @@ def execute(args, test=False): raise cmdutil.UserError("No comment entered.") body = body.decode('utf-8') elif args[1] == '-': # read body from stdin - body = sys.stdin.read() - if not body.endswith('\n'): - body+='\n' + binary = not options.content_type.startswith("text/") + if not binary: + body = sys.stdin.read() + if not body.endswith('\n'): + body+='\n' + else: # read-in without decoding + body = sys.__stdin__.read() else: # body = arg[1] body = args[1] if not body.endswith('\n'): diff --git a/becommands/depend.py b/becommands/depend.py index 8dbb2eb..0e9ee97 100644 --- a/becommands/depend.py +++ b/becommands/depend.py @@ -13,7 +13,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -"""Add/remove bug dependencies.""" +"""Add/remove bug dependencies""" from libbe import cmdutil, bugdir import os, copy __desc__ = __doc__ diff --git a/becommands/tag.py b/becommands/tag.py index 5a18a7c..ab0324e 100644 --- a/becommands/tag.py +++ b/becommands/tag.py @@ -13,7 +13,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -"""Tag a bug, or search bugs for tags.""" +"""Tag a bug, or search bugs for tags""" from libbe import cmdutil, bugdir import os, copy __desc__ = __doc__ diff --git a/doc/be.1.sgml b/doc/be.1.sgml index 5e6efc3..a2df21f 100644 --- a/doc/be.1.sgml +++ b/doc/be.1.sgml @@ -18,7 +18,7 @@ be.1: be.1.sgml <!ENTITY dhfirstname "<firstname>Ben</firstname>"> <!ENTITY dhsurname "<surname>Finney</surname>"> <!-- Please adjust the date whenever revising the manpage. --> - <!ENTITY dhdate "<date>2008-04-21</date>"> + <!ENTITY dhdate "<date>2009-06-25</date>"> <!-- SECTION should be 1-8, maybe w/ subsection other parameters are allowed: see man(7), man(1). --> <!ENTITY dhsection "<manvolnum>1</manvolnum>"> @@ -45,7 +45,7 @@ be.1: be.1.sgml &dhsurname; </author> <copyright> - <year>2008</year> + <year>2009</year> <holder>&dhusername;</holder> </copyright> &dhdate; @@ -88,125 +88,12 @@ be.1: be.1.sgml </refsect1> <refsect1> <title>COMMANDS</title> - <variablelist> <varlistentry> - <term><command>assign</command> - </term> - <listitem> - <para>Assign an individual or group to fix a bug - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><command>close</command> - </term> - <listitem> - <para>Close a bug - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><command>comment</command> - </term> - <listitem> - <para>Add a comment to a bug - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><command>diff</command> - </term> - <listitem> - <para>Compare bug reports with older tree - </para> - </listitem> - </varlistentry> - <varlistentry> <term><command>help</command> </term> <listitem> - <para>Print help for given subcommand - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><command>inprogress</command> - </term> - <listitem> - <para>Bug fixing in progress - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><command>list</command> - </term> - <listitem> - <para>List bugs - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><command>new</command> - </term> - <listitem> - <para>Create a new bug - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><command>open</command> - </term> - <listitem> - <para>Re-open a bug - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><command>set</command> - </term> - <listitem> - <para>Change tree settings - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><command>set-root</command> - </term> - <listitem> - <para>Assign the root directory for bug tracking - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><command>severity</command> - </term> - <listitem> - <para>Show or change a bug's severity level - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><command>show</command> - </term> - <listitem> - <para>Show a particular bug - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><command>target</command> - </term> - <listitem> - <para>Show or change a bug's target for fixing - </para> - </listitem> - </varlistentry> - <varlistentry> - <term><command>upgrade</command> - </term> - <listitem> - <para>Upgrade the bugs to the latest format + <para>Print help for be and a list of all available commands. </para> </listitem> </varlistentry> diff --git a/libbe/arch.py b/libbe/arch.py index cd0f3b2..441c5a9 100644 --- a/libbe/arch.py +++ b/libbe/arch.py @@ -240,9 +240,9 @@ class Arch(RCS): self._u_invoke_client("delete-id", path) def _rcs_update(self, path): pass - def _rcs_get_file_contents(self, path, revision=None): + def _rcs_get_file_contents(self, path, revision=None, binary=False): if revision == None: - return RCS._rcs_get_file_contents(self, path, revision) + return RCS._rcs_get_file_contents(self, path, revision, binary=binary) else: status,output,error = \ self._invoke_client("file-find", path, revision) diff --git a/libbe/bug.py b/libbe/bug.py index 28f5253..4f297f9 100644 --- a/libbe/bug.py +++ b/libbe/bug.py @@ -288,7 +288,7 @@ class Bug(settings_object.SavedSettingsObject): if show_comments == True: comout = self.comment_root.xml_thread(auto_name_map=True, bug_shortname=shortname) - ret += comout + ret += comout+'\n' ret += '</bug>' return ret diff --git a/libbe/bzr.py b/libbe/bzr.py index 98ca571..21030e2 100644 --- a/libbe/bzr.py +++ b/libbe/bzr.py @@ -56,9 +56,9 @@ class Bzr(RCS): self._u_invoke_client("remove", "--force", path) def _rcs_update(self, path): pass - def _rcs_get_file_contents(self, path, revision=None): + def _rcs_get_file_contents(self, path, revision=None, binary=False): if revision == None: - return RCS._rcs_get_file_contents(self, path, revision) + return RCS._rcs_get_file_contents(self, path, revision, binary=binary) else: status,output,error = \ self._u_invoke_client("cat","-r",revision,path) diff --git a/libbe/cmdutil.py b/libbe/cmdutil.py index 6be7540..5873607 100644 --- a/libbe/cmdutil.py +++ b/libbe/cmdutil.py @@ -79,11 +79,17 @@ def help(cmd=None): for name, module in iter_commands(): cmdlist.append((name, module.__desc__)) longest_cmd_len = max([len(name) for name,desc in cmdlist]) - ret = ["Bugs Everywhere - Distributed bug tracking\n", + ret = ["Bugs Everywhere - Distributed bug tracking", + "", + "usage: be [command] [command_options ...] [command_args ...]", + "or: be help", + "or: be help [command]", + "", "Supported commands"] for name, desc in cmdlist: numExtraSpaces = longest_cmd_len-len(name) ret.append("be %s%*s %s" % (name, numExtraSpaces, "", desc)) + return "\n".join(ret) def completions(cmd): diff --git a/libbe/comment.py b/libbe/comment.py index df5a63f..9fa4a30 100644 --- a/libbe/comment.py +++ b/libbe/comment.py @@ -16,6 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA +import email.mime.base, email.encoders import os import os.path import time @@ -150,11 +151,13 @@ class Comment(Tree, settings_object.SavedSettingsObject): def _get_comment_body(self): if self.rcs != None and self.sync_with_disk == True: import rcs - return self.rcs.get_file_contents(self.get_path("body")) + binary = not self.content_type.startswith("text/") + return self.rcs.get_file_contents(self.get_path("body"), binary=binary) def _set_comment_body(self, old=None, new=None, force=False): if (self.rcs != None and self.sync_with_disk == True) or force==True: assert new != None, "Can't save empty comment" - self.rcs.set_file_contents(self.get_path("body"), new) + binary = not self.content_type.startswith("text/") + self.rcs.set_file_contents(self.get_path("body"), new, binary=binary) @Property @change_hook_property(hook=_set_comment_body) @@ -236,13 +239,21 @@ class Comment(Tree, settings_object.SavedSettingsObject): """ if shortname == None: shortname = self.uuid + if self.content_type.startswith("text/"): + body = (self.body or "").rstrip('\n') + else: + maintype,subtype = self.content_type.split('/',1) + msg = email.mime.base.MIMEBase(maintype, subtype) + msg.set_payload(self.body or "") + email.encoders.encode_base64(msg) + body = msg.as_string() info = [("uuid", self.uuid), ("short-name", shortname), ("in-reply-to", self.in_reply_to), ("from", self._setting_attr_string("From")), ("date", self.time_string), ("content-type", self.content_type), - ("body", (self.body or "").rstrip('\n'))] + ("body", body)] lines = ["<comment>"] for (k,v) in info: if v not in [settings_object.EMPTY, None]: @@ -276,7 +287,10 @@ class Comment(Tree, settings_object.SavedSettingsObject): lines.append("") #lines.append(textwrap.fill(self.body or "", # width=(79-indent))) - lines.extend((self.body or "").splitlines()) + if self.content_type.startswith("text/"): + lines.extend((self.body or "").splitlines()) + else: + lines.append("Content type %s not printable. Try XML output instead" % self.content_type) # some comments shouldn't be wrapped... istring = ' '*indent diff --git a/libbe/git.py b/libbe/git.py index 401b5e5..5da1f86 100644 --- a/libbe/git.py +++ b/libbe/git.py @@ -70,9 +70,9 @@ class Git(RCS): self._u_invoke_client("rm", "-f", path) def _rcs_update(self, path): self._rcs_add(path) - def _rcs_get_file_contents(self, path, revision=None): + def _rcs_get_file_contents(self, path, revision=None, binary=False): if revision == None: - return RCS._rcs_get_file_contents(self, path, revision) + return RCS._rcs_get_file_contents(self, path, revision, binary=binary) else: arg = "%s:%s" % (revision,path) status,output,error = self._u_invoke_client("show", arg) diff --git a/libbe/hg.py b/libbe/hg.py index a7413af..9b566b9 100644 --- a/libbe/hg.py +++ b/libbe/hg.py @@ -59,9 +59,9 @@ class Hg(RCS): self._u_invoke_client("rm", path) def _rcs_update(self, path): pass - def _rcs_get_file_contents(self, path, revision=None): + def _rcs_get_file_contents(self, path, revision=None, binary=False): if revision == None: - return RCS._rcs_get_file_contents(self, path, revision) + return RCS._rcs_get_file_contents(self, path, revision, binary=binary) else: status,output,error = \ self._u_invoke_client("cat","-r",revision,path) diff --git a/libbe/rcs.py b/libbe/rcs.py index c0b92e7..9c2defe 100644 --- a/libbe/rcs.py +++ b/libbe/rcs.py @@ -40,8 +40,7 @@ def _get_matching_rcs(matchfn): rcs = module.new() if matchfn(rcs) == True: return rcs - else: - del(rcs) + del(rcs) return RCS() def rcs_by_name(rcs_name): @@ -173,14 +172,17 @@ class RCS(object): at path. """ pass - def _rcs_get_file_contents(self, path, revision=None): + def _rcs_get_file_contents(self, path, revision=None, binary=False): """ Get the file contents as they were in a given revision. Revision==None specifies the current revision. """ assert revision == None, \ "The %s RCS does not support revision specifiers" % self.name - f = codecs.open(os.path.join(self.rootdir, path), "r", self.encoding) + if binary == False: + f = codecs.open(os.path.join(self.rootdir, path), "r", self.encoding) + else: + f = open(path, "rb") contents = f.read() f.close() return contents @@ -205,7 +207,8 @@ class RCS(object): except OSError, e: if e.errno == errno.ENOENT: return False - raise e + except CommandError: + return False def detect(self, path="."): """ Detect whether a directory is revision controlled with this RCS. @@ -290,7 +293,7 @@ class RCS(object): at path. """ self._rcs_update(self._u_rel_path(path)) - def get_file_contents(self, path, revision=None, allow_no_rcs=False): + def get_file_contents(self, path, revision=None, allow_no_rcs=False, binary=False): """ Get the file as it was in a given revision. Revision==None specifies the current revision. @@ -299,18 +302,21 @@ class RCS(object): raise NoSuchFile(path) if self._use_rcs(path, allow_no_rcs): relpath = self._u_rel_path(path) - contents = self._rcs_get_file_contents(relpath,revision) + contents = self._rcs_get_file_contents(relpath,revision,binary=binary) else: f = codecs.open(path, "r", self.encoding) contents = f.read() f.close() return contents - def set_file_contents(self, path, contents, allow_no_rcs=False): + def set_file_contents(self, path, contents, allow_no_rcs=False, binary=False): """ Set the file contents under version control. """ add = not os.path.exists(path) - f = codecs.open(path, "w", self.encoding) + if binary == False: + f = codecs.open(path, "w", self.encoding) + else: + f = open(path, "wb") f.write(contents) f.close() diff --git a/xml/be-xml-to-mbox b/xml/be-xml-to-mbox index b0a4cba..e5fec3b 100755 --- a/xml/be-xml-to-mbox +++ b/xml/be-xml-to-mbox @@ -116,14 +116,17 @@ class Comment (LimitedAttrDict): print "Message-ID: <%s@%s>" % (self["uuid"], DEFAULT_DOMAIN) print "Date: %s" % self["date"] print "From: %s" % self["from"] - print "Content-Type: %s; charset=%s" % (self["content-type"], DEFAULT_ENCODING) - print "Content-Transfer-Encoding: 8bit" print "Subject: %s: %s" % (self["short-name"], bug["summary"]) if "in-reply-to" not in self.keys(): self["in-reply-to"] = bug["uuid"] print "In-Reply-To: <%s@%s>" % (self["in-reply-to"], DEFAULT_DOMAIN) - print "" - print self["body"] + if self["content-type"].startswith("text/"): + print "Content-Transfer-Encoding: 8bit" + print "Content-Type: %s; charset=%s" % (self["content-type"], DEFAULT_ENCODING) + print "" + print self["body"] + else: # content type and transfer encoding already in XML MIME output + print self["body"] print "" class BE_list_handler (ContentHandler): |