Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Unified Diff: client/libs/ar/writer.py

Issue 2049523004: luci-py: Tools for working with BSD style ar archives. (Closed) Base URL: https://github.com/luci/luci-py.git@master
Patch Set: Fixing for Maruel's review. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« client/libs/ar/reader.py ('K') | « client/libs/ar/reader.py ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: client/libs/ar/writer.py
diff --git a/client/libs/ar/writer.py b/client/libs/ar/writer.py
new file mode 100644
index 0000000000000000000000000000000000000000..bd411b02c2385231d3f7f12317ee80b6ee3d8afb
--- /dev/null
+++ b/client/libs/ar/writer.py
@@ -0,0 +1,109 @@
+# Copyright 2016 The LUCI Authors. All rights reserved.
+# Use of this source code is governed under the Apache License, Version 2.0
+# that can be found in the LICENSE file.
+
+import shutil
+
+
+class ArWriter(object):
+ """Write an ar archive to the given output buffer."""
+
+ # Mode sentinels
+ MODE_HEADER = []
M-A Ruel 2016/06/14 13:26:17 = object()
mithro 2016/06/16 11:37:11 Obsolete.
+ MODE_CONTENTS = []
+
+ def __init__(self, obuf):
+ self.obuf = obuf
M-A Ruel 2016/06/14 13:26:17 I'd prefer self._obuf and _ prefix for others too
mithro 2016/06/16 11:37:11 Obsolete.
+ self.obuf.write('!<arch>\n')
+ self.mode = ArWriter.MODE_HEADER
+ self.needspadding = False
+ self.bytesrequired = 0
+
+ def header(self, fp, size, modtime, ownerid, groupid, filemod):
+ """Write a file information to the archive."""
+ assert self.mode == ArWriter.MODE_HEADER
+ assert self.bytesrequired == 0
+
+ # File name, 16 bytes
+ self.obuf.write('#1/%-13s' % str(len(fp)))
M-A Ruel 2016/06/14 13:26:17 Can you use struct.pack() like you did with unpack
mithro 2016/06/16 11:37:11 No stuct.pack doesn't do this style of output (lef
+ # Modtime, 12 bytes
+ self.obuf.write('%-12i' % modtime)
+ # Owner ID, 6 bytes
+ self.obuf.write('%-6i' % ownerid)
+ # Group ID, 6 bytes
+ self.obuf.write('%-6i' % groupid)
+ # File mode, 8 bytes
+ self.obuf.write('%-8o' % filemod)
+
+ datasize = size+len(fp)
+ # File size, 10 bytes
+ self.obuf.write('%-10s' % datasize)
+ # File magic, 2 bytes
+ self.obuf.write('\x60\n')
+
+ # Filename - BSD variant
+ self.obuf.write(fp)
+
+ self.mode = ArWriter.MODE_CONTENTS
+ self.bytesrequired = size
+ self.needspadding = datasize % 2 != 0
+
+ def _write(self, ibuf=None, s=None):
M-A Ruel 2016/06/14 13:26:17 I think I'd prefer two functions. This is confusin
mithro 2016/06/16 11:37:11 Obsolete.
+ assert self.mode == ArWriter.MODE_CONTENTS
+ assert ibuf is not None or s is not None
+
+ if ibuf is not None:
+ start = ibuf.tell()
+ shutil.copyfileobj(ibuf, self.obuf)
+ end = ibuf.tell()
+ self.bytesrequired -= end-start
+
+ if s is not None:
+ self.obuf.write(s)
+ self.bytesrequired -= len(s)
+
+ if self.bytesrequired == 0:
M-A Ruel 2016/06/14 13:26:17 if not self._bytesrequired:
mithro 2016/06/16 11:37:11 Obsolete.
+ if self.needspadding:
+ self.obuf.write('\n')
+ self.mode = ArWriter.MODE_HEADER
+
+ def write(self, ibuf_or_str):
M-A Ruel 2016/06/14 13:26:17 I'd prefer a writestr() function and not try to gu
mithro 2016/06/16 11:37:11 Obsolete.
+ """Write the file body to the archive."""
+ try:
+ self._write(ibuf=ibuf_or_str)
+ except AttributeError:
+ self._write(s=ibuf_or_str)
+
+ def close(self):
+ """Close the archive. Will close the output buffer."""
+ assert self.bytesrequired == 0
+ assert self.mode == ArWriter.MODE_HEADER
+ self.obuf.close()
+
+
+class ArDefaultWriter(ArWriter):
+ """Write an ar archive using defaults to the given output buffer.
+
+ Only a file's name and content are needed to create the archive, all of the
+ modification time, user, group and mode information will be set to default
+ values. This means that you don't need to perform an expensive stat the file.
+ """
+ DEFAULT_MODTIME = 1447140471
+ DEFAULT_USER = 1000
+ DEFAULT_GROUP = 1000
+ DEFAULT_MODE = 0100640 # 100640 -- Octal
+
+ def header(self, name, size,
+ modtime=None, ownerid=None, groupid=None, filemod=None):
M-A Ruel 2016/06/14 13:26:17 I'd prefer to not expose these arguments at all.
mithro 2016/06/16 11:37:11 Obsolete.
+ assert modtime is None
+ assert ownerid is None
+ assert groupid is None
+ assert filemod is None
+ ArWriter.header(
+ self, name, size,
+ self.DEFAULT_MODTIME, self.DEFAULT_USER, self.DEFAULT_GROUP,
+ self.DEFAULT_MODE)
+
+ def add(self, name, data):
+ self.header(name, len(data))
+ self._write(s=data)
« client/libs/ar/reader.py ('K') | « client/libs/ar/reader.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698