From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Ivan Shmakov Newsgroups: gmane.emacs.bugs Subject: bug#19274: tar-mode.el: allow for adding new archive members Date: Sat, 06 Dec 2014 19:17:16 +0000 Message-ID: <87zjb0lhab.fsf@violet.siamics.net> References: <877fy7nmgt.fsf@violet.siamics.net> <87fvctn913.fsf@violet.siamics.net> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1417893504 31586 80.91.229.3 (6 Dec 2014 19:18:24 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sat, 6 Dec 2014 19:18:24 +0000 (UTC) To: 19274@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sat Dec 06 20:18:18 2014 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1XxKry-0003Ym-0L for geb-bug-gnu-emacs@m.gmane.org; Sat, 06 Dec 2014 20:18:18 +0100 Original-Received: from localhost ([::1]:55341 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XxKrx-0002II-EP for geb-bug-gnu-emacs@m.gmane.org; Sat, 06 Dec 2014 14:18:17 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:37495) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XxKro-0002I2-G2 for bug-gnu-emacs@gnu.org; Sat, 06 Dec 2014 14:18:13 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XxKrj-0004VZ-9v for bug-gnu-emacs@gnu.org; Sat, 06 Dec 2014 14:18:08 -0500 Original-Received: from debbugs.gnu.org ([140.186.70.43]:58406) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XxKri-0004VG-TZ for bug-gnu-emacs@gnu.org; Sat, 06 Dec 2014 14:18:03 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.80) (envelope-from ) id 1XxKri-0001JT-Ev for bug-gnu-emacs@gnu.org; Sat, 06 Dec 2014 14:18:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Ivan Shmakov Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 06 Dec 2014 19:18:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 19274 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 19274-submit@debbugs.gnu.org id=B19274.14178934515006 (code B ref 19274); Sat, 06 Dec 2014 19:18:02 +0000 Original-Received: (at 19274) by debbugs.gnu.org; 6 Dec 2014 19:17:31 +0000 Original-Received: from localhost ([127.0.0.1]:55619 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1XxKrB-0001If-SJ for submit@debbugs.gnu.org; Sat, 06 Dec 2014 14:17:30 -0500 Original-Received: from fely.am-1.org ([78.47.74.50]:43703) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1XxKr8-0001IV-LN for 19274@debbugs.gnu.org; Sat, 06 Dec 2014 14:17:28 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=siamics.net; s=a2013295; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date:Sender:References:Subject:To:From; bh=iYBj9SU+Q5lIUd1xGgcsYnmVd8A5grlb7QelUWyC/PI=; b=eNIbXWq9Mu84ye1LLAJDSakM1A5rIQnO1HuKJNJ0lAtJTGzb76UFYvqQgck+P69ACYBUvpMOUDhqp+NcAD8ux/DYvsJ09fD0GSbGTwfrknpSRcAhsIi/wKXV9yG72QMMvRhaqQDLuO4FiXGzm6gOBuBR2u1enCsRzVnfDGohnPI=; Original-Received: from [2a02:2560:6d4:26ca::1:1d] (helo=violet.siamics.net) by fely.am-1.org with esmtps (TLS1.2:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from ) id 1XxKr6-0005QL-PP for 19274@debbugs.gnu.org; Sat, 06 Dec 2014 19:17:25 +0000 Original-Received: from localhost ([::1] helo=violet.siamics.net) by violet.siamics.net with esmtps (TLS1.2:RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from ) id 1XxKqz-0002m6-8T for 19274@debbugs.gnu.org; Sun, 07 Dec 2014 02:17:17 +0700 Mail-Followup-To: 19274@debbugs.gnu.org In-Reply-To: (Stefan Monnier's message of "Sat, 06 Dec 2014 00:09:56 -0500") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 140.186.70.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:96920 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable >>>>> Stefan Monnier writes: Please consider the revised patch MIMEd. * tar-mode.el: Allow for adding new archive members. (tar-new-regular-file-header, tar--pad-to, tar--put-at) (tar-header-serialize): New functions. (tar-current-position): Split from tar-current-descriptor. (tar-current-descriptor): Use it. (tar-new-entry): New command. (tar-mode-map): Bind it. [=E2=80=A6] >> BTW, I wonder if it makes sense to split the make-tar-header form >> (with all the nil=E2=80=99s there) off tar-new-entry into a new >> (tar-new-regular-file-header filename &optional size time) function? (Done.) >> I guess that=E2=80=99d ease the creation of Tar archives from Emacs Lisp >> code; (and I already imagine some uses to that.) > BTW, if you're interested in hacking on tar-mode, I keep dreaming of > plugging it into file-name-handler-alist so you can just visit > /foo/bar.tar.gz/somefile, use dired on it, ... I=E2=80=99m not all that familiar with file-name-handler-alist, but I guess I could check it out. (Although at this point I=E2=80=99m simply interested in creating Tar archives from the contents of Emacs buffers, =E2=80=93 without having them saved into files, that is.) Curiously, what would be the sensible behavior for Emacs when the copy of the Tar archive kept in the *tar-data* buffer happens to differ to the on-disk state of the respective file? --=20 FSF associate member #7257 np. =D0=92=D1=81=D0=B5=D0=BB=D0=B5=D0=BD=D1=81= =D0=BA=D0=B0=D1=8F =D0=B1=D0=BE=D0=BB=D1=8C=D1=88=D0=B0=D1=8F =D0=BB=D1=8E= =D0=B1=D0=BE=D0=B2=D1=8C =E2=80=94 =D0=93=D1=80=D0=B0=D0=B6=D0=B4=D0=B0=D0= =BD=D1=81=D0=BA=D0=B0=D1=8F =D0=9E=D0=B1=D0=BE=D1=80=D0=BE=D0=BD=D0=B0 --=-=-= Content-Type: text/diff Content-Disposition: inline --- a/etc/NEWS 2014-11-27 11:36:08 +0000 +++ b/etc/NEWS 2014-12-06 19:03:35 +0000 @@ -340,6 +340,9 @@ `tildify-ignored-environments-alist' variables (as well as a few helper functions) obsolete. +** tar-mode: new `tar-new-entry' command, allowing for new members to +be added to the archive. + ** Obsolete packages --- --- a/lisp/tar-mode.el 2014-08-28 19:18:24 +0000 +++ b/lisp/tar-mode.el 2014-12-06 19:04:02 +0000 @@ -50,9 +50,6 @@ ;; ;; o chmod should understand "a+x,og-w". ;; -;; o It's not possible to add a NEW file to a tar archive; not that -;; important, but still... -;; ;; o The code is less efficient that it could be - in a lot of places, I ;; pull a 512-character string out of the buffer and parse it, when I could ;; be parsing it in place, not garbaging a string. Should redo that. @@ -369,6 +366,83 @@ write-date, checksum, link-type, and link-name." string) (tar-parse-octal-integer string)) +(defun tar-new-regular-file-header (filename &optional size time) + "Return a Tar header for a regular file. +The header will lack a proper checksum; use `tar-header-block-checksum' +to compute one, or request `tar-header-serialize' to do that. + +Other tar-mode facilities may also require the data-start header +field to be set to a valid value. + +If SIZE is not given or nil, it defaults to 0. +If TIME is not given or nil, assume now." + (make-tar-header + nil + filename + #o644 0 0 (or size 0) + (or time (current-time)) + nil ; checksum + nil nil + nil nil nil nil nil)) + +(defun tar--pad-to (pos) + (make-string (+ pos (- (point)) (point-min)) 0)) + +(defun tar--put-at (pos val) + (when val + (insert (tar--pad-to pos) val))) + +(defun tar-header-serialize (header &optional update-checksum) + "Return the serialization of a Tar HEADER as a string. +This function calls `tar-header-block-check-checksum' to ensure the +checksum is correct. + +When UPDATE-CHECKSUM is non-nil, update HEADER with the newly-computed +checksum before doing the check." + (with-temp-buffer + (set-buffer-multibyte nil) + (let ((encoded-name + (encode-coding-string (tar-header-name header) + tar-file-name-coding-system))) + (unless (< (length encoded-name) 99) + ;; FIXME: implement it + (error "Long file name support is not implemented")) + (insert encoded-name)) + (insert (tar--pad-to tar-mode-offset) + (format "%6o\0 " (logand #o777777 (tar-header-mode header))) + (format "%6o\0 " (logand #o777777 (tar-header-uid header))) + (format "%6o\0 " (logand #o777777 (tar-header-gid header)))) + (insert (tar--pad-to tar-size-offset) + (format "%11o " (tar-header-size header))) + (insert (tar--pad-to tar-time-offset) + (tar-octal-time (tar-header-date header)) + " ") + ;; omit tar-header-checksum (tar-chk-offset) for now + (tar--put-at tar-linkp-offset (tar-header-link-type header)) + (tar--put-at tar-link-offset (tar-header-link-name header)) + (when (tar-header-magic header) + (tar--put-at tar-magic-offset (tar-header-magic header)) + (tar--put-at tar-uname-offset (tar-header-uname header)) + (tar--put-at tar-gname-offset (tar-header-gname header)) + (let ((dmaj (tar-header-dmaj header)) + (dmin (tar-header-dmin header))) + (tar--put-at tar-dmaj-offset + (and dmaj (format "%7o\0" (logand #o7777777 dmaj)))) + (tar--put-at tar-dmin-offset + (and dmin (format "%7o\0" (logand #o7777777 dmin)))))) + (tar--put-at 512 "") + (let ((ck (tar-header-block-checksum (buffer-string)))) + (goto-char (+ (point-min) tar-chk-offset)) + (delete-char 8) + (insert (format "%6o\0 " ck)) + (when update-checksum + (setf (tar-header-checksum header) ck)) + (tar-header-block-check-checksum (buffer-string) + (tar-header-checksum header) + (tar-header-name header))) + ;; . + (buffer-string))) + (defun tar-header-block-checksum (string) "Compute and return a tar-acceptable checksum for this block." @@ -547,6 +621,7 @@ MODE should be an integer which is a file mode value." (define-key map "p" 'tar-previous-line) (define-key map "\^P" 'tar-previous-line) (define-key map [up] 'tar-previous-line) + (define-key map "I" 'tar-new-entry) (define-key map "R" 'tar-rename-entry) (define-key map "u" 'tar-unflag) (define-key map "v" 'tar-view) @@ -731,10 +806,14 @@ tar-file's buffer." (interactive "p") (tar-next-line (- arg))) +(defun tar-current-position () + "Return the `tar-parse-info' index for the current line." + (count-lines (point-min) (line-beginning-position))) + (defun tar-current-descriptor (&optional noerror) "Return the tar-descriptor of the current line, or signals an error." ;; I wish lines had plists, like in ZMACS... - (or (nth (count-lines (point-min) (line-beginning-position)) + (or (nth (tar-current-position) tar-parse-info) (if noerror nil @@ -948,6 +1027,37 @@ the current tar-entry." (write-region start end to-file nil nil nil t))) (message "Copied tar entry %s to %s" name to-file))) +(defun tar-new-entry (filename &optional index) + "Insert a new empty regular file before point." + (interactive "*sFile name: ") + (let* ((buffer (current-buffer)) + (index (or index (tar-current-position))) + (d-list (and (not (zerop index)) + (nthcdr (+ -1 index) tar-parse-info))) + (pos (if d-list + (tar-header-data-end (car d-list)) + (point-min))) + (new-descriptor + (tar-new-regular-file-header filename))) + ;; Update the data buffer; fill the missing descriptor fields. + (with-current-buffer tar-data-buffer + (goto-char pos) + (insert (tar-header-serialize new-descriptor t)) + (setf (tar-header-data-start new-descriptor) + (copy-marker (point) nil))) + ;; Update tar-parse-info. + (if d-list + (setcdr d-list (cons new-descriptor (cdr d-list))) + (setq tar-parse-info (cons new-descriptor tar-parse-info))) + ;; Update the listing buffer. + (save-excursion + (goto-char (point-min)) + (forward-line index) + (let ((inhibit-read-only t)) + (insert (tar-header-block-summarize new-descriptor) ?\n))) + ;; . + index)) + (defun tar-flag-deleted (p &optional unflag) "In Tar mode, mark this sub-file to be deleted from the tar file. With a prefix argument, mark that many files." --=-=-=--