Mercurial(hg) Cheatsheet for Xen ================================ Written by Andrew Warfield, extended by Michael Fetterman and Ian Pratt June 29, 2005, extended by Grzegorz Milos 04 July 2005. Overview -------- The Xen project has moved from BitKeeper to Mercurial for source control. This note aims to provide a quick guide to getting up and running with the new tools as quickly as possible, and is written from the perspective of someone who has been using BK. For a more detailed exposition, see the mecurial tutorial: http://www.serpentine.com/mercurial/index.cgi?Tutorial The Hg manpage is available at: http://www.selenic.com/mercurial/hg.1.html There's also a very useful FAQ that explains the terminology: http://www.selenic.com/mercurial/FAQ.html There's also a good README: http://www.selenic.com/mercurial/README Necessary software ------------------ Mercurial is available at: http://www.selenic.com/mercurial/ You will also need a Python version >= 2.3 How Mercurial is different from BK ---------------------------------- There are several pertinent differences between hg and bk. This section aims to give an overview of the conceptual differences between the two SCMs -- if you just want examples to get going, skip ahead to "Getting Xen". The key differences are: - No explicit per-file locking. You do not need to explicitly check a file out before editing it. - No notion (currently) of file renames. - A repository can have multiple active heads. - Automatic merge support is currently inferior to BK's. - No graphical tools. - No per-file revision history, only per-changeset (we never really used this anyhow) - Hg repositories tend to be rather bigger than Bk ones, but Hg does seem faster. Mercurial is based on the notion of changesets as complete, immutable, versions of the repository. You make changes to a working version of the repository that is based on a particular changeset. When you commit, you will generate a new child changeset with whatever changes you choose to apply. A major difference between Hg and BK is that you aren't forced to resolve conflicts immediately: BK forced you to resolve conflicts immediately on any merge, and it then immediately created a changeset with those conflicts' resolutions. Frequently, you then had to add yet another changeset to fixup the things for which the automatic merge yielded bad results. Hg puts the results of the merge into your work directory, and remembers what you merged with (so that it can later record both of the merge parents, if you decide to make a changeset), but it doesn't immediately create a changeset. A further feature of Hg is that it allows a repository to have multiple heads. This means that you can have changesets with no common descendent in one repository -- something BK won't allow. This is actually pretty neat. For example, it would in principle enable you to have both the 2.0-testing and unstable trees in a single repository. We shyed away from doing this as we thought the risk of commiting to the wrong head was too great. One slightly confusing aspect of Hg is that many of the commands have aliases, and hence when looking things up in the man page its not always obvious what the underlying command is. For example 'co' is actually an alias for the 'update' command, but 'co' seems to make more sense, at least to RCS refugees like me. Getting Xen ----------- The URL for the mainline Xen mercurial respository is: http://xenbits.xensource.com/xen-unstable.hg (similarly for xen-2.0 and xen-2.0-testing) You can point a browser and this and use Hg's web interface to view revision history, or use it as the nominated source when issuing "hg init" or "hg pull" commands. However, to avoid taxing the Mercurial server with a complete pull of the Xen repository, it is best to download a tarball of a seed repository from: http://www.cl.cam.ac.uk/Research/SRG/netos/xen/downloads/xen-unstable.hg.tar.gz (or copy from /usr/groups/netos/html/xen/downloads/xen-unstable.hg.tar.gz) Untar the repository on your disk, cd into it, and then pull the most recent changes: hg pull -u By default hg does not automatically checkout ('update') files from the repository as used to happen with bk. The above is equivalent to "hg pull; hg co" The repository parent is stored in a repository configuration file, .hg/hgrc, from the repository root. If you look at this file, you will see: | [paths] | default = http://xenbits.xensource.com/xen-unstable.hg "default" specifies the appropriate parent repository for hg to pull from. Hg allows you to pull additional repositories, for instance if you want to work between unstable and testing concurrently. The command "hg pull" simply adds changesets to your repository, without any merging of any kind. "hg pull -u" implies merging with the current state of your working directory. If you weren't already "updated" to your local repository's tip, you might be surprised to find yourself merging the results of the pull with a non-tip node in your local repository. Revision History ---------------- You can view the repository revision history with: hg history In practice, you'll probably want to use pipe the output through 'head' or 'more' as it prints the entire history. Looking at the first few lines of output, you can see the changeset at the head of the current branch, known as the 'tip' (the tip is automatically given a special tag to make it easy to refer to): | changeset: 5599:6cbf9ec05cd9e05c0c46a85df7fc00262633cd3d | tag: tip | user: kaf24@firebug.cl.cam.ac.uk | date: Tue Jun 28 18:47:14 2005 | summary: bitkeeper revision 1.1768 (42c18d2259NPELcGV7ohyZNh72ufSw) By default, Hg just shows the first line of the changset comments. You can find further information with "hg -v history". The changeset identifier has two parts, a _local_ monotonically increasing changeset id, 5599 above, and a _global_ hash, which follows the colon on the changeset line. The hash uniquely identifies the changeset and its lineage back to the root of the changeset tree -- it is useful for distributed management and so on. However, as it is a bit unruly, the local id will allow you to work easily with the local repo. Hg commands will take either identifier. Additionally, a tags mechanism lets you give common names to specific changesets. You should always use the global hash when referring to versions of the mainline Xen respoitory. With Bk you could often get away with using the shortform version, but with Hg the local ids are pretty much guaranteed to be different. Creating a child repository from an existing repository ------------------------------------------------------- If you wanted to create additional local child repositories, hg init [path or url] is effectively equivalent to bk clone. The major difference is that it should be run from the root of your new repository. So: bk clone /foo/bar would be replaced with: mkdir bar cd bar hg init /foo/bar NB: newer version of Hg support a 'clone' command that works in the same manner as bk. Editing files ------------- Normal edits may be made in place. File creation needs explicit marking, though deletes should be picked up automatically creation: touch a.txt (or otherwise created a file) hg add a.txt You can see what has changed using: hg status | C foo/foo.c | R foo/bar.c | ? a.txt This shows that in the current repo, foo.c has been changed, bar.c has been deleted, and a.txt is new, but has not been added. '?' changes to 'A' after "hg add a.txt". There is a .hgignore file which contains regexps of files that should be ignored when scanning for ne
/*
 * Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
 * Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * Neither the name of the <organization> nor the
 *      names of its contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "stdlib.h"
#include "string.h"
#include "gfx.h"

#define SCB_DEMCR (*(volatile unsigned *)0xE000EDFC)
#define CPU_RESET_CYCLECOUNTER do { SCB_DEMCR = SCB_DEMCR | 0x01000000; \
DWT_CYCCNT = 0; \
DWT_CTRL = DWT_CTRL | 1 ; } while(0)

static int uitoa(unsigned int value, char * buf, int max) {
    int n = 0;
    int i = 0;
    unsigned int tmp = 0;

    if (!buf)
        return -3;

    if (2 > max)
        return -4;

    i=1;
    tmp = value;
    if (0 > tmp) {
        tmp *= -1;
        i++;
    }
    for (;;) {
        tmp /= 10;
        if (0 >= tmp)
            break;
        i++;
    }
    if (i >= max) {
        buf[0] = '?';
        buf[1] = 0x0;
        return 2;
    }

    n = i;
    tmp = value;
    if (0 > tmp) {
        tmp *= -1;
    }
    buf[i--] = 0x0;
    for (;;) {
        buf[i--] = (tmp % 10) + '0';
        tmp /= 10;
        if (0 >= tmp) {
            break;
        }
    }
    if (-1 != i) {
        buf[i--] = '-';
    }

    return n;
}

void benchmark(void) {
    uint32_t i, pixels, ms, pps;
    char pps_str[25];
	coord_t height, width, rx, ry, rcx, rcy;
    color_t random_color;
	font_t font;

    gdispSetOrientation(GDISP_ROTATE_90);

	width = gdispGetWidth();
	height = gdispGetHeight();
    font = gdispOpenFont("UI2 Double");

	gdispDrawStringBox(0, 0, width, 30, "ChibiOS/GFX - Benchmark", font, White, justifyCenter);

	font = gdispOpenFont("UI2");
	gdispDrawStringBox(0, height/2, width, 30, "5000 random rectangles", font, White, justifyCenter);
	
	gfxSleepMilliseconds(3000);
	
	/* seed for the rand() */
	srand(DWT_CYCCNT);
	pixels = 0;

	CPU_RESET_CYCLECOUNTER;

	for (i = 0; i < 5000; i++) {
		random_color = (rand() % 65535);
		rx = (rand() % (width-10));
		ry = (rand() % (height-10));
		rcx = (rand() % ((width-rx)-10))+10;
		rcy = (rand() % ((height-ry)-10))+10;

		gdispFillArea(rx, ry, rcx, rcy, random_color);
		pixels += (rcx+1)*(rcy+1);
	}

	ms = DWT_CYCCNT / 168000;
	pps = (float)pixels/((float)ms/1000.0f);

	memset (pps_str, 0, sizeof(pps_str));
	uitoa(pps, pps_str, sizeof(pps_str));
	strcat(pps_str, " Pixels/s");

	font = gdispOpenFont("UI2 Double");
	gdispClear(Black);
	gdispDrawStringBox(0, 0, width, 30, "ChibiOS/GFX - Benchmark", font, White, justifyCenter);
	gdispDrawStringBox(0, height/2, width, 30, pps_str, font, White, justifyCenter);
	//gdispDrawString(20, height/2, pps_str, font, White);
}

int main(void) {
	gfxInit();
	
	benchmark();
    
	while(TRUE) {
		gfxSleepMilliseconds(500);
	}

	return 0;
}