filetime_from_git.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import os
  4. from git import Git, Repo, InvalidGitRepositoryError
  5. from pelican import signals, contents
  6. from datetime import datetime
  7. from time import mktime, altzone
  8. try:
  9. repo = Repo(os.path.abspath('.'))
  10. git = Git(os.path.abspath('.'))
  11. except InvalidGitRepositoryError as e:
  12. repo = None
  13. def filetime_from_git(content):
  14. if isinstance(content, contents.Static) or repo is None:
  15. return
  16. gittime = content.metadata.get('gittime', 'yes').lower()
  17. gittime = gittime.replace("false", "no").replace("off", "no")
  18. if gittime == "no":
  19. return
  20. # 1. file is not managed by git
  21. # date: fs time
  22. # 2. file is staged, but has no commits
  23. # date: fs time
  24. # 3. file is managed, and clean
  25. # date: first commit time, update: last commit time or None
  26. # 4. file is managed, but dirty
  27. # date: first commit time, update: fs time
  28. path = content.source_path
  29. status, stdout, stderr = git.execute(['git', 'ls-files', path, '--error-unmatch'],
  30. with_extended_output=True, with_exceptions=False)
  31. if status != 0:
  32. # file is not managed by git
  33. content.date = datetime.fromtimestamp(os.stat(path).st_ctime)
  34. else:
  35. # file is managed by git
  36. commits = repo.commits(path=path)
  37. if len(commits) == 0:
  38. # never commited, but staged
  39. content.date = datetime.fromtimestamp(os.stat(path).st_ctime)
  40. else:
  41. # has commited
  42. content.date = datetime.fromtimestamp(mktime(commits[-1].committed_date) - altzone)
  43. status, stdout, stderr = git.execute(['git', 'diff', '--quiet', 'HEAD', path],
  44. with_extended_output=True, with_exceptions=False)
  45. if status != 0:
  46. # file has changed
  47. content.updated = datetime.fromtimestamp(os.stat(path).st_ctime)
  48. else:
  49. # file is not changed
  50. if len(commits) > 1:
  51. content.updated = datetime.fromtimestamp(mktime(commits[0].committed_date) - altzone)
  52. if not hasattr(content, 'updated'):
  53. content.updated = content.date
  54. def register():
  55. signals.content_object_init.connect(filetime_from_git)