具有双向同步功能的OneDrive客户端
onedrive-sync-client的Python项目详细描述
双向单驱动器同步客户端
disclaimer:此实用程序处于早期阶段。虽然它的设计是为了在检测到冲突时尽快失败,以避免数据丢失,但不能保证您的数据绝对安全。在知道发生了什么之前,在测试环境中运行它
基于用python编写的Microsoft Graph,此实用程序将检测您在本地所做的更改和在云中发生的更改,并尝试在两侧合并它们。如果由于冲突而失败,例如,您在本地重命名了一个文件,但在手机上用另一个文件名分配了同一个文件,则此实用程序将在执行任何操作之前投诉并失败,以确保数据保持完整。 要试用它,只需在终端中键入(假设您使用的是gnu/linux,而 目前,这个实用程序利用extended attributes在本地保存文件标识符,而现代文件系统和发行版在默认情况下应该启用这个功能。将创建一个sqlite数据库,并将其用作中心位置,以保存首次运行时的基本信息,如上次同步时的login token或整个文件系统树的状态。我们将要求您授予访问OneDrive文件(当然)和“随时访问您的信息”的权限,这意味着您不必每次使用时都进行登录和授权。 一个重要的背景是,与几乎所有云存储提供商一样,OneDrive会为每个文件或目录(文件夹)分配一个全局唯一的标识符,因为该标识符还链接到其他元数据,如是否允许匿名访问者查看该文件,以及元数据列表随时可能增长。这有效地降低了算法的复杂度。 首先,在两侧构建文件系统树层次结构。OneDrive为我们提供了a simple API以递归方式将整个树转储到云上,其中包含每个项的标识符和名称,此外,每个文件的校验和(当前实现不同)。利用上述信息容易构造本地树,并且可以从每个文件或目录的扩展属性中读取标识符信息。您可以通过 然后是三棵树,云树,本地树和保存的树。我们需要以双向方式合并它们。然后将云树与保存的树进行比较。尽管我们称它们为“树”,但它们实际上是按其标识符排序的节点列表。每个节点存储其名称、校验和(如果适用)以及其父节点的标识符。对于每个标识符,如果对应的节点在云树和保存的树中相同,则视为未更改。即使其父节点被重命名或移动,只要其父节点的标识符保持不变,该节点也将与其父节点一起移动。如果标识符只存在于云树中,则必须是新创建的;如果仅存在于基本树中,则必须在上次同步之后从云中移除该标识符。如果其父项的标识符不同,则必须移动它。如果其名称或校验和已更改,则必须重命名或重写。然后,我们在云树之间得到一个变化集还有那棵被拯救的树。为本地树所做的类似方法,但是由于会有重复的标识符,对于每个重复,将保留其中最相似的标识符,而其他标识符将被视为新创建的标识符。这不是最优的,因为如果我们在本地复制一个文件夹,会有大量的上传流量,因为我们需要上传整个文件夹。 现在我们有两个变更集,一个在云树和保存的树之间,另一个在本地树和保存的树之间。每个变更集由多个操作组成,每个操作都属于下列类型之一: 从上一步生成的这个集合是无序的,但是它们必须按顺序应用。这些步骤的某些排列是可以接受的,但其他的则会导致冲突。例如,不能在创建父文件之前创建该文件。操作可能与同一集合中的操作冲突,该集合表示从保存的树到新树的实际可能更改顺序;它们也可能与另一集合中的操作冲突,这可能导致合并过程无法实现。 有两种冲突。其中一个是两个集合之间的冲突,即两个集合不能同时修改同一个节点。另一种是,实际上不仅仅是冲突,而是在一个变更集中进行排序,并让它被排序。这两个集合之间不需要考虑顺序,因为云集合必须在本地集合之后应用,实际上它已经在本地集合之前应用。 对于每个标识符,对应的节点不能应用冲突操作。冲突操作可能不会发生在一个变更集中,而只发生在两个变更集中,因为它们是从同一棵树生成的。具有完全相同参数的两个操作不冲突,但如果不冲突,则它们在具有相同类型的操作时相互冲突。此外,删除节点与该节点上的任何其他操作都有冲突。此处不需要考虑添加节点,因为在同一标识符上不会有其他操作。 排序问题是一个拓扑排序问题。每一个操作都被建模为一个顶点,如果一个操作在另一个操作之后发生,它们之间会有一条有方向的边。此图中的循环表示冲突。 为了发现不同标识符之间的冲突,对每个操作的先决条件和效果进行标记和索引。有两种类型的先决条件,以及两种对应类型的效果:给定的目录存在,给定目录内的给定名称没有被占用。操作应该在这些操作之后应用,为其先决条件提供相应的效果。 实际上,有些情况不在该算法的范围内,例如,创建两个具有不同标识符(当然)但在同一目录下具有相同名称的文件是不会被检测到的。这种冲突发生在两个变更集之间,并且只与名称冲突相关。应该有更多未公开的冲突,因此在应用之前应该测试生成的脚本。 拓扑排序后,生成的脚本将应用于两棵树的测试副本,如果有删除目录的操作,则从该目录中删除项的任何操作都可以标记为忽略,作为优化。 rest api在Microsoft Graph documentation site中进行了描述,有一些地方需要特别注意。树作为标识符和属性表保存到数据库中。 OneDrive为dump the whole tree提供了一个API。这棵树可能很大,传输过程可能很慢。为了解决这个问题,可以保存上次转储查询的结果,并使用delta api生成真正的云树。当delta api不可用时,可以使用回退方法。 请求代理可用于临时存储请求,并在任何强制刷新之前使用batch API保存通信量。另外,一些http库还支持htp2.0以另外节省流量。然而,这涉及到一个更复杂的算法。 由于OneDrive支持部分下载,因此需要一个下载管理器,特别是当文件很大时。有两个上传api,还需要一个上传管理器。在良好的网络条件下,{a10}更易于使用,并且适合于小于4mib的文件。当文件太大或网络状况不好时,必须使用^{ 这个项目是根据GNU Affero General Public License授权的。~/.local/bin
在您的$PATH
)中即可pip install --user onedrive-sync-client # Install
# If you want to use the latest snapshot use the following line instead
# pip install --user https://github.com/gzxu/onedrive-sync-client/archive/master.zip
onedrive --set-location ~/OneDrive # Config
onedrive # Sync!
算法
getfattr -n user.onedrive.id FILENAME
检查本地存储的标识符。最初使用扩展属性是因为它与相应的文件一起移动,但是默认的文件管理器nautilus在复制文件时复制所有扩展属性。这将导致重复的标识符。此外,对于新的本地创建的文件,将没有标识符,因此本地构建的树需要为每个文件分配一个临时标识符,并维护实际标识符和临时标识符之间的映射。同时,还加载上次同步时树的保存状态。冲突检查和脚本排序
先决条件:目的地必须存在
先决条件:目的地必须存在
先决条件:目的地必须存在
先决条件:目的地必须存在
脚本检查和优化
应用脚本并保存树
delta列表
批量请求
文件下载和上传
已知问题
未来工作
尽可能在处理数据库时使用DAO许可证
推荐PyPI第三方库