2009-12-19 6 views
1

Например, скажем, я переместил файл с /project/file.cs в /project/subdir/file.cs. Было бы неплохо, если nautilus автоматически преобразует это значение в bzr mv /project/file.cs /project/subdir/file.cs. Можно ли это настроить?Есть ли способ заставить Nautilus перемещать файлы под управлением версии с помощью команды перемещения VCS?

Было бы неплохо, если бы я был предупрежден, когда делал простой старый mv на файлах с контролируемой версией, но я полагаю, что это отдельный вопрос.

ответ

2

Как вы уже указали сами, вам в основном нужно что-то, что слушает ходы, поэтому я подумал, что что-то подделал, чтобы дать вам указание, как это будет работать.

Я пробовал использовать gio.FileMonitor, но в конце концов вернулся к использованию простой старой pyinotify, потому что у последнего есть встроенная поддержка для обнаружения переименования/перемещения файлов.

import pyinotify 

import bzrlib 
from bzrlib.workingtree import WorkingTree 
from bzrlib.errors import NotBranchError, BzrRenameFailedError 

directories_to_watch = [ 
    # Add the paths to your working copies/branches to watch here 
] 

wm = pyinotify.WatchManager() 

# When you listen to both MOVED_FROM and MOVED_TO the event for MOVED_TO will include both 
# pathname (new path) and src_pathname (previous path). 
mask = pyinotify.IN_MOVED_FROM | pyinotify.IN_MOVED_TO 

class EventHandler(pyinotify.ProcessEvent): 

    def process_IN_MOVED_TO(self, event): 
     try: 
      tree, path = WorkingTree.open_containing(event.src_pathname) 
      root = event.src_pathname[:-len(path)] # Ugh, hackish 

      if not path.startswith(".bzr"): # Also hackish (to exclude events for anything in the .bzr subdirectory) 
       try: 
        tree.lock_tree_write() 
        source = event.src_pathname[len(root):] # Again hackish 
        target = event.pathname[len(root):] # Same 
        tree.rename_one(source, target) 
        print "Renamed %s to %s" % (source, target) 
       except BzrRenameFailedError: # Same 
        pass 
       finally: 
        tree.unlock() 
     except NotBranchError: 
      return 

handler = EventHandler() 
notifier = pyinotify.Notifier(wm, handler) 

for path in directories_to_watch: 
    wdd = wm.add_watch(path, mask, rec=True, auto_add=True) 
    print "Recursively watching %s" % path 

notifier.loop() 

Вот как это работает:

$ mv afile bfile 
$ bzr status 
renamed: 
    afile => bfile 

$ mv bfile foobar/ 
$ bzr status 
renamed: 
    afile => foobar/bfile 

$ mv foobar/ zoobar 
$ bzr status 
renamed: 
    afile => zoobar/bfile 
    foobar/ => zoobar/ 

$ mv zoobar/ foobar 
$ bzr status 
renamed: 
    afile => foobar/bfile 

$ mv foobar/bfile afile 

И мы туда, где мы начали ;-)

[править]

Если вы не хотите вручную перечислить различные каталоги, чтобы посмотреть, что может быть хорошей идеей написать расширение Nautilus, которое отслеживает различные рабочие копии, с которыми он сталкивается, поскольку вы навигации. Вот кое-что, чтобы вы начали (это входит в ~/.nautilus/python-extensions):

import os 
import pickle 

import nautilus 

import gio 

from xdg import BaseDirectory as basedir 

import bzrlib 
from bzrlib.workingtree import WorkingTree 
from bzrlib.errors import NotBranchError 

class BzrMonitor(nautilus.InfoProvider, nautilus.MenuProvider): 

    data_directory = basedir.save_data_path("bzrmonitor") 
    data_filename = os.path.join(data_directory, "workingcopies.db") 

    def __init__(self): 
     print "Initializing BzrMonitor extension..." 

     try: 
      data_file = open(self.data_filename, "r") 
      self.data = pickle.load(data_file) 
     except IOError: 
      self.data = [] 
      data_file = open(self.data_filename, "w") 
      pickle.dump(self.data, data_file) 
      data_file.close() 

    def detect_and_save_branch(self, path): 
     try: 
      tree, rel_path = WorkingTree.open_containing(path) 

      # TODO: Still can't figure out how to get the path from the tree itself 
      if len(rel_path) > 0: 
       root = path[:-len(rel_path)] 
      else: 
       root = path 

      root = root.rstrip(os.path.sep) 

      if root not in self.data: 
       print "Added not seen before branch %s to cache..." % root 
       self.data.append(root) 
       data_file = open(self.data_filename, "w") 
       pickle.dump(self.data, data_file) 
       data_file.close() 

     except NotBranchError: 
      return 

    def update_file_info(self, item): 
     """ 
     This function is called when: 

      - When you enter a directory (once for each item but only when the 
      item was modified since the last time it was listed) 
      - When you refresh (once for each item visible) 
      - When an item viewable from the current window is created or modified 
     """ 
     self.detect_and_save_branch(gio.File(item.get_uri()).get_path()) 

    def get_file_items(self, window, items): 
     """ 
     Menu activated with items selected. Nautilus also calls this function 
     when rendering submenus, even though this is not needed since the entire 
     menu has already been returned. 
     """ 

     pass 

    def get_background_items(self, window, item): 
     """ 
     Menu activated on entering a directory. Builds context menu for File 
     menu and for window background. 
     """ 

     self.detect_and_save_branch(gio.File(item.get_uri()).get_path()) 

заимствовали различные строки документации из кода ;-)

расширения RabbitVCS в В вашем мониторе вы, вероятно, хотите, чтобы посмотреть файл workingcopies.db для добавляет и регистрирует часы на любых новых рабочих копиях, которые он нашел.

Ресурсы

+0

Ты потрясающий! Конечно, есть некоторые ограничения. Чтобы вручную просмотреть каталоги, которые вы хотите посмотреть, это боль, и это не удается, если вы переместите файл в каталог, который еще не добавлен в bzr. Но для ответа на вопрос от незнакомца в Интернете это здорово! Я посмотрю и посмотрю, смогу ли я уточнить скрипт, когда буду его использовать. –

+0

*/blush * Спасибо за добрые слова :-) Чтобы не было необходимости вручную перечислять каталоги, которые вы хотите просмотреть, может быть хорошей идеей создать расширение Nautilus, которое отслеживает, где ваши рабочие копии, когда вы перемещаетесь вдоль , Я добавил пример. Мне было бы очень интересно узнать, что вы придумали. –

1

Как один из разработчиков RabbitVCS, я уверен, что такой вещи в настоящее время невозможно. Nautilus extensions может предоставлять контекстные меню, страницы свойств, дополнительные столбцы и отвечать на файл, отображаемый в главном окне браузера. Они не могут зацепиться за такие события, как перемещение или удаление. (Мне бы это понравилось, если бы это было так, но сейчас это не приоритет.) Вы бы сами модифицировали API расширения Nautilus.

Если вы догадываетесь об этом, но не знаете, с чего начать, вы должны посмотреть источник Nautilus и задать Nautilus mailing list. Они могли бы сказать вам, если вы лаяете по неправильному дереву об этом.

Возможно, что расширение Nautilus является неправильным местом для такого рода вещей. Это можно сделать с GVFS вместо расширения Nautilus, но я не в своей глубине.

+0

Я думаю, что промахнулись. – detly

+0

Интересно!Я пропустил это, когда вы разместили его. Я не думаю, что вам обязательно нужно зацепиться за Наутилуса. Например, Dropbox запускает демон, который прослушивает такие события, как удаление, перемещение, переименование и т. Д. Это не требует Nautilus, вы можете запустить его в среде с командной строкой. Я не знаю, как это работает, но это возможно. –

+0

Oooh ... Я понимаю, что вы говорите. Одной из вещей, которые я сейчас рассматриваю для RabbitVCS, является добавление мониторов файловой системы в корень рабочей копии для обновления кэша при изменениях. (например, gio.GileMonitor, или использовать интерфейс pyinotify в Linux.) Не знаете, как бы вы сделали это глобально, хотя с добавлением рекурсивного монитора событий на «/» ... и я не знаю, будут ли проблемы связанные с этим. – detly

 Смежные вопросы

  • Нет связанных вопросов^_^