GSync


Introduction

What is GSync?

GSync, or Generic Sync, is a generalized merge tool that enables you to merge arbitrary files through a so called merge description. Various situations present the need to keep files in sync which may have been edited by several persons simultaneously. Version control systems such as Subversion offer a very powerful tool for such situations. However, such systems work in a manner that suits source code very well but may not work optimally for other kinds of files. All changes are always applied everywhere and conflicts have to be manually resolved. This is where GSync comes in. GSync allows you to specify exactly what should happen in the case of a conflict within a certain type of file, as well as which parts to keep synchronized and how. For instance, you might want to share IDE configuration throughout your team. However, such configuration files are likely to contain parts that you don't want to share, such as GUID's that are per-pc unique or less important settings such as fonts and colors. In that case, you can write an MDL (Merge Description Language) file containing information about the entries that you want to keep synchronized and GSync will handle this - and leave everything else as is.

GSyncis developed by BestBrains Aps, a Danish software development consultancy company specializing in agile methods and test driven development. It is open source, released under the MIT license and hosted on

Download

You can download the latest source code here: gsync-0.1.zip.

Getting Started

Installation and Prerequisites

GSync requires the .NET framework version 1.1 or later.

GSync works as is but the real power comes when used together with a version control system. We recommend Subversion, one of the most powerful version control systems available.

A simple example

An MDL file contains two major elements: documents and locations. A document describes how to merge a specific file type, where as a location specifies that a file that should be merged is present somewhere. Let's say you want to synchronize your FireFox setup across a number of machines. This example shows how to merge the prefs.js file - the preferences file for the FireFox browser. Now, this file is full of lines like these:

user_pref("browser.download.manager.alertOnEXEOpen", false);
user_pref("browser.download.save_converter_index", 1);
user_pref("browser.link.open_external", 3);

Now, what we want is for the document to recognize a user_pref line as a "section". Comments and other code should be ignored. Hence, we define our section to match the regular expression "\r\nuser_pref\("(.*)",.*\);". This will match exactly such a line. In there, the key should be the first parameter to the user_pref function. As GSync currently doesn't support regex groups, we have to sepcify the key a little less specific. This is no big problem as the keys are only used for internal accounting. The regular expression user_pref\("(.*)" will use the beginning of the string, up until the second parameter as the key. Now, given such keys, GSync is capable of recognizing identical sections, even if they have different values as the second parameter. The actions that are specified in the "rules" section defines what it should do with them.


<mergeDefinition  xmlns='http://www.bestbrains.biz/mdl.xsd'>
	<documents>
		<document name="all">
			<sections>
				<section name='prefs' match='regexp:\r\nuser_pref\("(.*)",.*\);'>
					<keys>
						<key match='regexp:user_pref\("(.*)"' />
					</keys>
					<rules>
						<!-- These are default rules. They're just explicitly defined for
						demonstration purposes.. -->
						
						<onMyAddition><add/></onMyAddition>
						<onTheirAddition><add/></onTheirAddition>
						<onMyDeletion><delete/></onMyDeletion>
						<onTheirDeletion><delete/></onTheirDeletion>
						<onMyChange><changeTheirs/></onMyChange>
						<onTheirChange><changeMine/></onTheirChange>
						
						<!-- I Win in case of a conflict.. -->
						<onConflict><changeTheirs/></onConflict>
						
					</rules>
				</section>
			</sections>
		</document>
	</documents>
</mergeDefinition>

Very good. We now have an MDL file which knows how to merge prefs.js files. All we need now is to specify where such files can be found. There are two ways to do this. You can either specify filenames at the command line, or you can write the location into the mdl file. This is done using a "location" tag. Such a tag describes where to find the file. Furthermore, it describes where the stored version is to be found, and which protocols should be used to fetch the files. The current version only supports the basic file: protocol. Now, in order to synchronize changes, GSync requires three versions of the same file: the active, the stored and a shadow. The active version is the one that is being used. The stored version is the one that serves as a backup or central synchronization origin. The shadow version is the active version as it looked the last time we synchronized. Given these three files, GSync is able to tell which parts have been added and removed, and which have been changed. The basic file protocol automatically copies the active file to filename.extension.shadow. If we had our repository located at c:\repositories, and we want our FireFox prefs.js file backed up from there, we could add something like this to our mdl file:


<mergeDefinition>

  ...
 
    <locations>
        <location>
            <active>file://C:\Program Files\Mozilla Firefox\defaults\profile\prefs.js</active>
            <stored>file://C:\repositories\FireFox Configuration\prefs.js</stored>
        </location>
    </locations>

  ...

</mergeDefinition>

Now, given this, you can synchronize the two files and thereby back up your configuration, share it between computers and whatnot.

Changelog

0.1 - July 12 2005:

  • Initial release