例如,假设我将一个文件/project/file.cs
从/project/subdir/file.cs
. 如果 nautilus 自动将其转换为bzr mv /project/file.cs /project/subdir/file.cs
. 可以这样设置吗?
如果我在mv
对版本控制文件执行简单的旧操作时被警告,那也很好,但我想这是一个单独的问题。
例如,假设我将一个文件/project/file.cs
从/project/subdir/file.cs
. 如果 nautilus 自动将其转换为bzr mv /project/file.cs /project/subdir/file.cs
. 可以这样设置吗?
如果我在mv
对版本控制文件执行简单的旧操作时被警告,那也很好,但我想这是一个单独的问题。
就像您已经表明自己一样,您基本上需要一些可以监听移动的东西,所以我想我会编写一些代码来告诉您这是如何工作的。
我尝试使用 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
文件的添加内容并在它找到的任何新工作副本上注册监视。
资源
作为RabbitVCS的开发人员之一,我很确定这样的事情目前是不可能的。Nautilus 扩展可以提供上下文菜单、属性页、附加列,它们可以响应浏览器主窗口中显示的文件。他们不能与移动或删除等任意事件挂钩。(如果是这样的话,我会很高兴,但这不是我们现在的优先事项。)您应该自己修改 Nautilus 扩展 API。
如果您觉得可以,但不知道从哪里开始,您应该查看 Nautilus 源并在Nautilus 邮件列表中询问。他们当然可以告诉你,如果你在这件事上找错了树。
Nautilus 扩展可能是这种事情的错误位置。可以使用GVFS而不是 Nautilus 扩展来做一些事情,但我对此并不了解。