c6cc0f9c0ff68fea380a80d783858052781bad61
[htsworkflow.git] / htsworkflow / util / hashfile.py
1 """Utility to make md5sums of a file caching as a parallel file
2 """
3 import logging
4 import os
5 from subprocess import Popen, PIPE
6
7 from django.utils.encoding import smart_text
8
9 logger = logging.getLogger(__name__)
10
11 def make_md5sum(filename):
12     """Quickly find the md5sum of a file
13     """
14     md5_cache = os.path.join(filename+".md5")
15     if os.path.exists(md5_cache):
16         logger.debug("Found md5sum in {0}".format(md5_cache))
17         stream = open(md5_cache,'rt')
18         lines = stream.readlines()
19         md5sum = parse_md5sum_line(lines, filename)
20     else:
21         md5sum = make_md5sum_unix(filename, md5_cache)
22     return md5sum
23     
24 def make_md5sum_unix(filename, md5_cache):
25     cmd = ["md5sum", filename]
26     logger.debug("Running {0}".format(" ".join(cmd)))
27     p = Popen(cmd, stdout=PIPE)
28     stdin, stdout = p.communicate()
29     retcode = p.wait()
30     logger.debug("Finished {0} retcode {1}".format(" ".join(cmd), retcode))
31     if retcode != 0:
32         logger.error("Trouble with md5sum for {0}".format(filename))
33         return None
34     lines = stdin.split(os.linesep)
35     md5sum = parse_md5sum_line(lines, filename)
36     if md5sum is not None:
37         logger.debug("Caching sum in {0}".format(md5_cache))
38         stream = open(md5_cache, "wt")
39         stream.write(smart_text(stdin))
40         stream.close()
41     return md5sum
42
43 def parse_md5sum_line(lines, filename):
44     md5sum, md5sum_filename = smart_text(lines[0]).split()
45     md5sum_filename = os.path.basename(md5sum_filename)
46     filename = os.path.basename(filename)
47     if md5sum_filename != filename:
48         errmsg = "MD5sum and I disagre about filename. {0} != {1}"
49         logger.error(errmsg.format(filename, md5sum_filename))
50         return None
51     return md5sum
52