User:Mak77
Mercurial backout script
This is a work-in-progress script usable to simplify backouts.
UPDATE: Steve Fink ported this to an hg extension called qbackout, you can find it at https://bitbucket.org/sfink/qbackout
WARNING: It will destroy any uncommited changes in the current tree, so be sure to save your work.
On Mac you need to "port install gsed" and replace all sed calls with gsed, due to non-standard implementation of sed.
################################################################################ # backout # # Pass all wanted changesets as arguments, using Mercurial REV syntax. # When the script is done, just "hg qfin -a && hg push" # # Examples: # * All changesets between b31507c8ca17 and 1f551298a760 (included), plus # changeset 4f57f89653df # - backout b31507c8ca17:1f551298a760 4f57f89653df # * A single changeset # - backout tip # - backout 4f57f89653df backout() { if [ $# -lt 1 ] then echo "Pass me some changeset number!" return 1 fi echo "Reverting tree to a clean status." hg update -C 2>&1 | (! grep '^abort:') || { echo "Failed to clean update the tree."; return 1; } hg qpop -a 2>&1 | (! grep '^abort:') || { echo "Failed to qpop all patches."; return 1; } hg pull 2>&1 | (! grep '^abort:') || { echo "Failed to pull."; return 1; } hg update default 2>&1 | (! grep '^abort:') || { echo "Failed to update to default."; return 1; } echo "Sorting changesets from newer to older." local RANGES="" for ENTRY in $* do local RANGE="" # Convert everything to ranges, since it's faster to batch them. if [[ "$ENTRY" == *:* ]] then # Ensure correct order in the range, from newer to older. local RANGE=$(hg log -r $ENTRY --template '{rev} {node|short}\n' | sort -n -r | cut -d" " -f2) local NEWER=$(echo -ne "$RANGE" | sed -n '1p') local OLDER=$(echo -ne "$RANGE" | sed -n '$p') RANGE="$(hg log -r $NEWER --template '{rev}') $NEWER:$OLDER" else RANGE=$(hg log -r $ENTRY --template '{rev} {node|short}:{node|short}') fi if [ "$RANGE" = "" ] then echo "Changeset not found." return 1 fi RANGES="$RANGES\n$RANGE" done RANGES=$(echo -ne "$RANGES" | sort -n -r | cut -d" " -f2) echo "Creating backout patches in mq." local MESSAGE="Backout " for RANGE in $RANGES do echo " - $RANGE" local CSET=$(expr "$RANGE" : '\(.*\):.*') local PARENT=$(hg parents -r $(expr "$RANGE" : '.*:\(.*\)') --template '{node|short}') # Check for multiple parents, if so the changeset is a merge. if [ ${#PARENT} -gt 12 ] then echo "Multiple parents found. Backing out merges is not yet supported." return 1 fi hg update $CSET 2>&1 | (! grep '^abort:') || { echo "Failed to update to changeset."; return 1; } hg revert -a -r $PARENT 2>&1 | (! grep '^abort:') || { echo "Failed to revert to parent changeset."; return 1; } hg qdelete $CSET.diff > /dev/null 2>&1 hg qnew -f $CSET.diff 2>&1 | (! grep '^abort:') || { echo "Failed to create partial backout patch."; return 1; } hg qpop 2>&1 | (! grep '^abort:') || { echo "Failed to qpop partial backout patch."; return 1; } # Search for a bug number in the commit message. MESSAGE="$MESSAGE$(hg log -r $RANGE --template '{node|short} {desc|fill68|firstline}\n' | sed -n -e 's/\([a-z0-9]\{12\}\) \(.*bug.\([0-9]\{5,\}\).*\|.*\)/\1 (bug \3)/ip' | sed 's/ (bug )//' | sed ':a;N;$!ba;s/\n/, /g')," done echo "Folding backout patches to backout.diff." hg update -r default 2>&1 | (! grep '^abort:') || { echo "Failed to revert to default."; return 1; } hg qdelete backout.diff > /dev/null 2>&1 hg qnew backout.diff -m "$MESSAGE" 2>&1 | (! grep '^abort:') || { echo "Failed to create backout patch."; return 1; } for RANGE in $RANGES do echo " - $RANGE" local CSET=$(expr "$RANGE" : '\(.*\):.*') # qfold doesn't return a nonzero exit code on failure :( if hg qfold $CSET.diff 2>&1 | grep '^abort:' then echo "Failed to qfold backout patch, possible code conflicts." hg qpop -a > /dev/null 2>&1 hg qdelete backout.diff > /dev/null 2>&1 hg qdelete $CSET.diff > /dev/null 2>&1 return 1 fi done # Protect against pushing empty backout patches. if [ "$(hg log -r qtip --template '{files}')" = "" ] then echo "Empty backout patch. Giving up." hg qpop -a > /dev/null 2>&1 hg qdelete backout.diff > /dev/null 2>&1 return 1 fi hg qrefresh -e echo -ne "\nOutgoing backout:\n" hg outgoing -q --template '{author}\n{desc}\n\n - Modified files:\n{file_mods}\n\n - Removed files:\n{file_dels}\n\n - Added files:\n{file_adds}\n\n' }
Colorize mach
This is inherited from the original colorize pymake from Dolske, then further improved by Sdwilsh
Requires updated sed (for unbuffered option) from https://bugzilla.mozilla.org/show_bug.cgi?id=373784
See my blog post: http://blog.bonardo.net/2013/03/05/colorize-mach
mach() { # ANSI colors. _black=$(echo -e "\E[30m") _red=$(echo -e "\E[31m") _green=$(echo -e "\E[32m") _yellow=$(echo -e "\E[33m") _blue=$(echo -e "\E[34m") _magenta=$(echo -e "\E[35m") _cyan=$(echo -e "\E[36m") _white=$(echo -e "\E[37m") _bright=$(echo -e "\E[1m") _reset=$(echo -e "\E[0m") # Shortcuts for quick styling. _time=$_green _misc=$_bright$_black _info=$_cyan _result=$_bright$_green _warning=$_bright$_yellow _error=$_bright$_red _leak=$_bright$_magenta ./mach $@ 2>&1 | sed -r -u \ -e "s/^(.+)(:\swarning|warning:\s)(.+)$/$_warning\1\2\3$_reset/i" \ -e "s/(leaked\s[0-9]+)(.+)$/$_leak\1\2$_reset/i" \ -e "s/(adding:?|creating library|generating)(.+)$/\1$_info\2$_reset/i" \ -e "s/(changing directory to:|processing script file:)(.+)$/\1$_info\2$_reset/i" \ -e "s/^(\s?\S+\s){1}(processing\s)(\S+)$/\1\2$_info\3$_reset/" \ -e "s/^(.+)(interrupted|\serror)(\s.+)$/$_error\1\2\3$_reset/i" \ -e "s/^(.?)(finished)(.+)$/$_result\1\2\3$_reset/i" \ -e "s/^(\s?\S+\s+\-*\s?){1}(\S+)$/\1$_misc\2$_reset/" \ -e "s/(TEST-PASS|result summary:|passed: [1-9]{1}[0-9]*)/$_result\1$_reset/i" \ -e "s/(TEST-INFO)/$_info\1$_reset/i" \ -e "s/(TEST-UNEXPECTED-\S+|failed: [1-9]{1}[0-9]*)/$_error\1$_reset/i" \ -e "s/^(\s?[0-9]+\:[0-9]+\.[0-9]+\s)/$_time\1$_reset/" }
Colorize pymake
This is inherited from the original colorize pymake from Dolske, then further improved by Sdwilsh
Requires updated sed from https://bugzilla.mozilla.org/show_bug.cgi?id=373784
The objdir uses target applications, like browser/ I usually work from the topsrcdir
################################################################################ # echoes the objdir objdir() { echo "$(ls -d obj*)/browser" } ################################################################################ # build helper. 'build' for full build, 'build path/to/dir' for incremental. # You can pass additional targets and options like 'build path/to/dir clean'. # build toolkit/library for libxul build() { if [ "$OSTYPE" = "msys" ] then # Colorize pymake. # ANSI color codes. # 0-7 == black, red, ... white # 3_ = set foreground color # 4_ = set background color ansi_black=$(echo -e "\E[30m") ansi_red=$(echo -e "\E[31m") ansi_green=$(echo -e "\E[32m") ansi_yellow=$(echo -e "\E[33m") ansi_blue=$(echo -e "\E[34m") ansi_magenta=$(echo -e "\E[35m") ansi_cyan=$(echo -e "\E[36m") ansi_white=$(echo -e "\E[37m") # make colors brighter ansi_bright=$(echo -e "\E[1m") # return to terminal default ansi_reset=$(echo -e "\E[0m") fi if [ $# -gt 0 ] then what2build="-C $(objdir)/$@" else what2build="-f client.mk" fi if [ "$OSTYPE" = "msys" ] then python -OO build/pymake/make.py -j12 $what2build 2>&1 | sed -r -u \ -e "s/(TEST-UNEXPECTED-[A-Z]+.*)$/$ansi_bright$ansi_red\1$ansi_reset/" \ -e "s/(TEST-PASS)/$ansi_green\1$ansi_reset/" \ -e "s/(TEST-INFO)/$ansi_cyan\1$ansi_reset/" \ -e "s/(.+)(return code)(.+)/$ansi_red\1$ansi_bright\2\3$ansi_reset/" \ -e "s/^([a-z]\:\\\.+(\.exe|\.py).+)/$ansi_bright$ansi_black\1$ansi_reset/" \ -e "s/^(\s+.+)/$ansi_bright$ansi_black\1$ansi_reset/" \ -e "s/(Entering directory )(.+)/\1$ansi_cyan\2$ansi_reset/" \ -e "s/(Leaving directory )(.+)/\1$ansi_bright$ansi_black\2$ansi_reset/" \ -e "s/(evaluation from )(.+)/\1$ansi_bright$ansi_black\2$ansi_reset/" \ -e "s/(.+ \: )(warning .+)/$ansi_yellow\1$ansi_bright\2$ansi_reset/" \ -e "s/(.+ \: )((fatal )?error .+)/$ansi_red\1$ansi_bright\2$ansi_reset/" \ -e "s/(.+\: )(Found error)/\1$ansi_red$ansi_bright\2$ansi_reset/" \ -e "s/(No rule to make target .+)/$ansi_red$ansi_bright\1$ansi_reset/" else make -j12 $what2build fi cd $(hg root) }