Linux 有没有办法让Nautilus使用VCS'在版本控制下移动文件;移动命令?
例如,假设我将一个文件从Linux 有没有办法让Nautilus使用VCS'在版本控制下移动文件;移动命令?,linux,version-control,bazaar,nautilus,Linux,Version Control,Bazaar,Nautilus,例如,假设我将一个文件从/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
时收到警告也会很好,但我想这是一个单独的问题。作为的开发人员之一,我很确定这样的事情目前是不可能的。可以提供上下文菜单、属性页和其他列,它们可以响应浏览器主窗口中显示的文件。他们不能与移动或删除等任意事件挂钩。(如果是这样的话,我很乐意,但这不是我们现在的优先事项。)您应该自己修改Nautilus扩展API
如果你觉得可以,但不知道从哪里开始,你应该看看鹦鹉螺的来源,并在网上询问。如果你在这件事上找错了人,他们肯定会告诉你的
有可能鹦鹉螺的延伸是这种事情的错误地点。也许可以用GVFS而不是Nautilus扩展来做一些事情,但我对此一无所知。就像你已经指出的那样,你基本上需要一些可以监听移动的东西,所以我想我应该编写一些代码,让你知道这是如何工作的 我尝试使用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
):
我从RabbitVCS的扩展代码中借用了各种docstring;-)
在监视器中,您可能需要查看workingcopies.db
文件中的添加内容,并在找到的任何新工作副本上注册手表
资源
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())