aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTharre <tharre3@gmail.com>2015-05-25 00:14:40 +0200
committerTharre <tharre3@gmail.com>2015-05-25 00:14:40 +0200
commit6eb59b79ddc5c69fc9a90f3f90408b6fdafb1836 (patch)
tree869f2de8e1ed5e21c125ed9ebe9cf5565b11c824
parent4678d9630e9f95db9d06d3423c539bcb0bcc722c (diff)
downloadredo-6eb59b79ddc5c69fc9a90f3f90408b6fdafb1836.tar.gz
redo-6eb59b79ddc5c69fc9a90f3f90408b6fdafb1836.tar.xz
redo-6eb59b79ddc5c69fc9a90f3f90408b6fdafb1836.zip
Store dependencies as plain text instead of binary
Binary files are hard to debug, and even while the code required to parsing them is simpler it's not worth the tradeoff. Note that handling of newlines in target names is not implemented yet, they require some sort of special escaping.
-rwxr-xr-xprint_dep.py55
-rw-r--r--src/build.c71
2 files changed, 51 insertions, 75 deletions
diff --git a/print_dep.py b/print_dep.py
deleted file mode 100755
index 803b5e9..0000000
--- a/print_dep.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/env python3
-
-# quick and dirty utility to make the binary mess, produced by my redo program
-# into something more friendly to the human eye
-# requires termcolor (pip install termcolor)
-
-import struct
-import sys
-import hashlib
-from binascii import hexlify
-from os.path import basename
-from termcolor import colored
-
-def convert_back(s):
- return s.replace('!', '/')
-
-if (len(sys.argv) < 2):
- print("Need an argument.")
- exit(1)
-
-hasher = hashlib.sha1()
-file = open(sys.argv[1], 'rb')
-magic = file.read(4)
-hash = file.read(20)
-subdeps = file.read()
-org_file = convert_back(basename(sys.argv[1]))
-
-hash_str = str(hexlify(hash), 'ascii')
-
-with open(org_file, 'rb') as f:
- buf = f.read()
- hasher.update(buf)
-
-print("Target: " + org_file)
-print("Hash: " + hash_str + " ", end="")
-if hasher.hexdigest() == hash_str:
- print(colored(u"\u2714", "green", attrs=['bold']))
-else:
- print(colored(u"\u2718", "red", attrs=['bold']))
-
-print("Magic number: " + str(struct.unpack('i', magic)[0]))
-print("Dependencies:")
-start = True
-thing = ""
-for byte in subdeps:
- if start:
- print(" " + chr(byte) + "-", end="")
- start = False
- elif byte == 0:
- start = True
- print(thing)
- thing = ""
- else:
- thing += chr(byte)
- continue
diff --git a/src/build.c b/src/build.c
index 479b6a0..daef371 100644
--- a/src/build.c
+++ b/src/build.c
@@ -27,8 +27,7 @@
#define _FILENAME "build.c"
#include "dbg.h"
-#define HASHSIZE sizeof(((dep_info*)0)->hash)
-#define HEADERSIZE (sizeof(dep_info)-offsetof(dep_info, magic))
+#define HEADERSIZE 60
typedef struct do_attr {
char *specific;
@@ -88,11 +87,11 @@ int build_target(const char *target) {
if (!fp) {
if (errno != ENOENT)
fatal("redo: failed to open %s\n", dep.path);
- memset(dep.hash, 0, HASHSIZE); // FIXME
+ memset(dep.hash, 0, 20); /* FIXME */
} else {
if (fseek(fp, sizeof(unsigned), SEEK_SET))
fatal("redo: fseek() failed");
- if (fread(dep.hash, 1, HASHSIZE, fp) < HASHSIZE)
+ if (fread(dep.hash, 1, 20, fp) < 20)
fatal("redo: failed to read stuff");
fclose(fp);
}
@@ -159,9 +158,9 @@ int build_target(const char *target) {
unsigned char new_hash[20];
hash_file(target, new_hash);
- retval = memcmp(new_hash, dep.hash, HASHSIZE);
+ retval = memcmp(new_hash, dep.hash, 20);
if (retval)
- memcpy(dep.hash, new_hash, HASHSIZE);
+ memcpy(dep.hash, new_hash, 20);
write_dep_info(&dep);
} else {
@@ -338,6 +337,9 @@ static char *get_dep_path(const char *target) {
void add_dep(const char *target, const char *parent, int ident) {
char *dep_path = get_dep_path(parent);
+ if (strchr(target, '\n'))
+ fatal("Newlines in targets are not supported.");
+
int fd = open(dep_path, O_WRONLY | O_APPEND);
if (fd < 0) {
if (errno != ENOENT)
@@ -351,16 +353,19 @@ void add_dep(const char *target, const char *parent, int ident) {
}
char garbage[HEADERSIZE];
+ memset(garbage, 'Z', HEADERSIZE);
/* skip header */
if (lseek(fd, 0, SEEK_END) < (off_t) HEADERSIZE)
pwrite(fd, garbage, HEADERSIZE, 0);
char *reltarget = get_relpath(target);
- int bufsize = strlen(reltarget) + 2;
+ int bufsize = strlen(reltarget) + 3;
char *buf = xmalloc(bufsize);
buf[0] = ident;
- strcpy(buf+1, reltarget);
+ buf[1] = '\t';
+ strcpy(buf+2, reltarget);
+ buf[bufsize-1] = '\n';
if (write(fd, buf, bufsize) < bufsize)
fatal("redo: failed to write to %s", dep_path);
@@ -392,6 +397,16 @@ static void hash_file(const char *target, unsigned char *hash) {
fclose(in);
}
+void sha1_to_hex(const unsigned char *sha1, char *buf) {
+ static const char hex[] = "0123456789abcdef";
+
+ for (int i = 0; i < 20; ++i) {
+ char *pos = buf + i*2;
+ *pos++ = hex[sha1[i] >> 4];
+ *pos = hex[sha1[i] & 0xf];
+ }
+}
+
/* Write the dependency information into the specified path. */
static void write_dep_info(dep_info *dep) {
mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
@@ -399,7 +414,15 @@ static void write_dep_info(dep_info *dep) {
if (out < 0)
fatal("redo: failed to open %s", dep->path);
- if (write(out, &dep->magic, HEADERSIZE) < (ssize_t) HEADERSIZE)
+ char buf[60];
+ sprintf(buf, "%010u", dep->magic);
+ buf[10] = '\t';
+ sha1_to_hex(dep->hash, buf+11);
+ buf[51] = '\t';
+ memset(buf+52, '-', 7);
+ buf[59] = '\n';
+
+ if (write(out, buf, sizeof buf) < (ssize_t) sizeof buf)
fatal("redo: failed to write dependency info to '%s'", dep->path);
if (close(out))
@@ -443,29 +466,36 @@ static int handle_c(const char *target) {
free(dep_path);
- dep_info *dep = (dep_info*) (buf-offsetof(dep_info, magic));
+ errno = 0;
+ buf[10] = '\0';
+ long magic = strtol(buf, NULL, 10);
+ if (errno)
+ return build_target(target);
if (!fexists(target)) {
- if (dep->flags & DEP_SOURCE)
+ if (buf[52] == 'S') /* source flag set */
/* target is a source and must not be rebuild */
return 1;
else
return build_target(target);
}
- if (dep->magic == (unsigned) atoi(getenv("REDO_MAGIC")))
+ if (magic == (unsigned) atoi(getenv("REDO_MAGIC")))
/* magic number matches */
return 1;
+ unsigned char hash[20];
+ char char_hash[40];
- bool rebuild = false;
- unsigned char hash[HASHSIZE];
hash_file(target, hash);
- if (memcmp(hash, dep->hash, HASHSIZE))
+ sha1_to_hex(hash, char_hash);
+ buf[51] = '\0';
+ if (memcmp(char_hash, buf+11, 40))
return build_target(target);
char *ptr;
char *root = getenv("REDO_ROOT");
+ bool rebuild = false;
while (!feof(fp)) {
ptr = buf;
@@ -475,24 +505,25 @@ static int handle_c(const char *target) {
fatal("redo: failed to read %zu bytes from descriptor", sizeof buf);
for (size_t i = 0; i < read; ++i) {
- if (buf[i])
+ if (buf[i] != '\n')
continue;
- if (!is_absolute(&ptr[1])) {
+ buf[i] = '\0';
+ if (!is_absolute(&ptr[2])) {
/* if our path is relative we need to prefix it with the
root project directory or the path will be invalid */
- char *abs = concat(3, root, "/", &ptr[1]);
+ char *abs = concat(3, root, "/", &ptr[2]);
if (update_target(abs, ptr[0]))
rebuild = true;
free(abs);
} else {
- if (update_target(&ptr[1], ptr[0]))
+ if (update_target(&ptr[2], ptr[0]))
rebuild = true;
}
ptr = &buf[i+1];
}
- if (read && buf[read-1]) {
+ if (read && buf[read-1] != '\n') {
if (buf != ptr)
memmove(buf, ptr, buf-ptr + sizeof buf);
else