/SparkleShare/Nautilus/sparkleshare-nautilus3-extension.py.in

http://github.com/hbons/SparkleShare · Autoconf · 200 lines · 115 code · 51 blank · 34 comment · 14 complexity · c35dd383ba3d681d86154efb98a77857 MD5 · raw file

  1. #!/usr/bin/python
  2. # SparkleShare, an instant update workflow to Git.
  3. # Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. import os
  18. import shutil
  19. import time
  20. import urllib
  21. # http://projects.gnome.org/nautilus-python/documentation/html/
  22. from gi.repository import Nautilus, GObject, Gtk, Gdk
  23. SPARKLESHARE_PATH = os.path.join (os.path.expanduser ('~'), "SparkleShare")
  24. import gettext
  25. gettext.bindtextdomain('sparkleshare', '@prefix@/share/locale')
  26. gettext.textdomain('sparkleshare')
  27. _ = gettext.gettext
  28. class SparkleShareExtension (GObject.GObject, Nautilus.MenuProvider):
  29. def __init__ (self):
  30. pass
  31. def checkout_version (self, menu, file_path, commit_hash, username, timestamp):
  32. file_name = os.path.basename (file_path)
  33. tmp_file_path = os.path.join (SPARKLESHARE_PATH, ".tmp", file_name)
  34. # Move the current version to a temporary path
  35. shutil.move (file_path, tmp_file_path)
  36. # Check out the earlier version
  37. os.chdir (os.path.dirname (file_path))
  38. os.popen ("git checkout " + commit_hash + " '" + file_name + "'")
  39. new_tmp_file_name = file_name + " (" + username + ", "
  40. new_tmp_file_name += time.strftime ("%H:%M %d %b %Y", timestamp).replace (" 0", " ") + ") "
  41. # Rename the checked out file
  42. shutil.move (file_name, new_tmp_file_name)
  43. # Move the original file back
  44. shutil.move (tmp_file_path, file_path)
  45. return True
  46. def format_web_link (self, path):
  47. # Get the remote url used for the repo
  48. self.chdir_to_repo_base(path)
  49. url_command = os.popen ("git config --get remote.origin.url")
  50. origin_url = url_command.readline ().strip ()
  51. if not origin_url:
  52. return
  53. # Get components
  54. # TODO use regex here or something not so ugly
  55. protocol, remaining = origin_url.split ("://", 1)
  56. host, origin_path = remaining.split("@")[1].split("/", 1);
  57. # Format the right web url depending on the service
  58. repo_base = self.get_repo_base_path(path)
  59. relative_path = path.split(repo_base, 1)[1].lstrip("/")
  60. #url = url.rstrip (".git")
  61. if "gitorious.org" in host:
  62. # ssh://git@gitorious.org/gnome-design/gnome-design.git
  63. # http://gitorious.org/gnome-design/gnome-design/blobs/raw/master/COPYING
  64. url = "http://" + host + "/" + urllib.quote(origin_path.rstrip(".git")) + "/blobs/master/" + urllib.quote(relative_path)
  65. elif "github.com" in host:
  66. # ssh://git@github.com/hbons/SparkleShare.git
  67. # https://raw.github.com/hbons/SparkleShare/master/README
  68. url = "http://raw.github.com/" + urllib.quote(origin_path.rstrip(".git")) + "/raw/master/" + urllib.quote(relative_path)
  69. else:
  70. # https://git.one-gear.com/?p=thansen/Public.git;a=blob;f=SparkleShare.txt;hb=HEAD
  71. url = "http://" + host + "/?p=" + urllib.quote(origin_path) +";a=blob;f=" + urllib.quote(relative_path) + ";hb=HEAD"
  72. return url
  73. def copy_web_link (self, menu, path):
  74. url = self.format_web_link(path)
  75. clipboard = Gtk.Clipboard.get (Gdk.Atom.intern ("CLIPBOARD", False))
  76. clipboard.set_text (url, -1)
  77. clipboard.store ()
  78. return
  79. def chdir_to_repo_base(self, file_path):
  80. base_path = self.get_repo_base_path(file_path)
  81. os.chdir(base_path)
  82. def get_repo_base_path(self, path):
  83. path = os.path.abspath(path)
  84. parts = path.split(SPARKLESHARE_PATH, 1)[1].split("/")
  85. if len(parts) > 1:
  86. sub_folder = parts[1]
  87. else:
  88. sub_folder = parts[0]
  89. return SPARKLESHARE_PATH + "/" + sub_folder
  90. def get_file_items (self, window, files):
  91. # Only work if one file is selected
  92. if len (files) != 1:
  93. return
  94. file_reference = files [0]
  95. # Only work if we're in a SparkleShare repository folder
  96. if file_reference.is_directory ():
  97. return
  98. if not (file_reference.get_parent_uri ().startswith ('file://' + SPARKLESHARE_PATH)):
  99. return
  100. if file_reference.get_parent_uri () == 'file://' + SPARKLESHARE_PATH:
  101. return
  102. file_path = urllib.unquote ('/' + file_reference.get_uri ().lstrip('file:/'))
  103. url = self.format_web_link (file_path)
  104. parent_path = os.path.dirname (os.path.abspath (file_path))
  105. top_menuitem = Nautilus.MenuItem (name="Nautilus::SparkleShare",
  106. label="SparkleShare")
  107. top_submenu = Nautilus.Menu ()
  108. top_menuitem.set_submenu (top_submenu)
  109. web_link_menu_item_copy = Nautilus.MenuItem (name="Nautilus::CopyWebLink",
  110. label=_("Copy Web Link"),
  111. tip=_("Copy the web address of this file to the clipboard"))
  112. web_link_menu_item_copy.connect ("activate", self.copy_web_link, file_path)
  113. epochs = ["", "", "", "", "", "", "", "", "", ""]
  114. commit_hashes = ["", "", "", "", "", "", "", "", "", ""]
  115. time_command = os.popen ("git log -10 --format='%at' '" + file_path + "'")
  116. author_command = os.popen ("git log -10 --format='%an' '" + file_path + "'")
  117. hash_command = os.popen ("git log -10 --format='%H' '" + file_path + "'")
  118. i = 0
  119. for line in time_command.readlines ():
  120. epochs [i] = line.strip ("\n")
  121. i += 1
  122. # Only work if there is history
  123. if i < 2:
  124. top_submenu.append_item (web_link_menu_item_copy)
  125. return [top_menuitem]
  126. i = 0
  127. for line in hash_command.readlines ():
  128. commit_hashes [i] = line.strip ("\n")
  129. i += 1
  130. earlier_version_menu_item = Nautilus.MenuItem (name="Nautilus::OpenOlderVersion",
  131. label=_("Get Earlier Version"),
  132. tip=_("Make a copy of an earlier version in this folder"))
  133. version_submenu = Nautilus.Menu ()
  134. i = 0
  135. for line in author_command.readlines ():
  136. if i > 0:
  137. timestamp = time.strftime ("%d %b\t%H:%M", time.localtime (float (epochs [i])))
  138. username = line.strip ("\n")
  139. menu_item = Nautilus.MenuItem (name="Nautilus::Version" + epochs [i],
  140. label=timestamp + "\t" + username,
  141. tip=_("Select to get a copy of this version"))
  142. menu_item.connect ("activate", self.checkout_version, file_path, commit_hashes [i],
  143. username, time.localtime (float (epochs [i])))
  144. version_submenu.append_item (menu_item)
  145. i += 1
  146. earlier_version_menu_item.set_submenu (version_submenu)
  147. top_submenu.append_item (earlier_version_menu_item)
  148. top_submenu.append_item (web_link_menu_item_copy)
  149. return [top_menuitem]