Mercurial > hg > mercurial-talk
view revset-talk.tex @ 301:027862d2fec9
Slide on quoting
author | Martin Geisler <mg@lazybytes.net> |
---|---|
date | Wed, 08 Jun 2011 14:00:24 +0200 |
parents | 6420e2bdb651 |
children | 78a5a27609a5 |
line wrap: on
line source
\documentclass[t,noamsthm,xcolor=dvipsnames]{beamer} \input{preambel} \title{Mercurial's Query Languages} \author{Martin Geisler \texorpdfstring{\\$\langle$\texttt{mg@aragost.com}$\rangle$} {<mg@aragost.com>}} \date{gearconf 2011} \begin{document} \begin{frame}[plain] \maketitle \begin{tikzpicture}[overlay, remember picture] \node[above right] at (current page.south west) {\includegraphics[height=3cm]{pixelman-front}}; \end{tikzpicture} \end{frame} \begin{frame}{Outline} \tableofcontents \end{frame} \section{Introduction} \begin{frame}[fragile]{Quoting} How to handle special characters: \begin{itemize}[<+->] \item You will need to quote your revsets on the command line: \begin{lstlisting} $ hg log -r parents() zsh: parse error near `()' \end{lstlisting} \item Strings in revsets can be in single- or double-quotes: \begin{lstlisting} $ hg log -r "user('Martin')" \end{lstlisting} \item Escape characters are supported \begin{lstlisting} $ hg log -r "keyword('first line\nsecond line')" \end{lstlisting} \item Use a raw string to disable the escape characters: \begin{lstlisting} $ hg log -r "grep(r'Bug\s*\d+')" \end{lstlisting} \end{itemize} \end{frame} \section{Revision Sets} \subsection{Predicates} \begin{frame}[fragile]{Predicates} Predicates select changesets for inclusion in the resulting set: \begin{itemize} \item Changeset metadata: \cmd{closed()}, \cmd{head()}, \cmd{merge()}, \cmd{author(string)}, \cmd{date(interval)}, Closed heads: \begin{lstlisting} $ hg log -r "head() and closed()" \end{lstlisting} Reopened branches: \begin{lstlisting} $ hg log -r "closed() and not head()" \end{lstlisting} \begin{lstlisting} $ hg log -r "author('Martin') and merge()" \end{lstlisting} \end{itemize} bisected(string) grep(regex) keyword(string) \cmd{adds(pattern)} \cmd{contains(pattern)} \cmd{file(pattern)} \cmd{filelog(pattern)} \cmd{modifies(pattern)} \cmd{removes(pattern)} \end{frame} \begin{frame}{Functions} ancestor(single, single) ancestors(set) children(set) descendants(set) follow([file]) heads(set) outgoing([path]) p1([set]) p2([set]) parents([set]) present(set) roots(set) \end{frame} \begin{frame}{Final Touches on Your Query} Trimming, cutting, manipulating the set: \begin{itemize}[<+->] \item \cmd{max(set)}, \cmd{min(set)}: the changeset with minimum/maximum revision number in the set \item \cmd{reverse(set)}: the set is an ordered set; this reverses it \item \cmd{limit(set, n)}, \cmd{last(set, n)}: the first/last $n$ changesets \item \cmd{sort(set[, [-]key...])}: sorting the set by revision number, branch name, changeset message, user name, or date \end{itemize} \end{frame} \begin{frame}[fragile]{Solving Ambiguities} When you do \cmd{hg log -r "foo"}, Mercurial checks \begin{enumerate} %\item revision number %\item full changeset ID \item is \cmd{foo} a bookmark? \item is \cmd{foo} a tag? \item is \cmd{foo} a branch name? %\item partial changeset ID \end{enumerate} First match wins. You can override this using predicates: \begin{itemize}[<+->] %\item \cmd{rev(number)} %\item \cmd{id(hash)} \item \cmd{bookmark([name])}, \cmd{tag([name])}: the changeset with the given bookmark or tag, or all bookmarked/tagged changesets \item \cmd{branch(name)}: changesets on the given branch \item \cmd{branch(set)}: changesets on the branches of the given set, normally used with a single changeset: \begin{lstlisting} $ hg log -r "branch(tip)" \end{lstlisting} \end{itemize} \end{frame} \subsection{Operators} \begin{frame}{Operators} \end{frame} \begin{frame}[fragile]{Examples} \begin{itemize} \item Changes that need to be merged into the default branch: \begin{lstlisting} $ hg log -r "ancestors(stable) - ancestors(default)" $ hg log -r "::stable - ::default" \end{lstlisting} \item Heads on the current branch: \begin{lstlisting} $ hg log -r "head() and branch(.)" \end{lstlisting} \item Open heads on the current branch: \begin{lstlisting} $ hg log -r "head() and branch(.) and not closed()" \end{lstlisting} \item Bugfixes that are not in a tagged release: \begin{lstlisting} $ hg log -r "keyword(bug) and not ::tagged()" \end{lstlisting} \end{itemize} \end{frame} \section{File Sets} \begin{frame}{Selecting Files} \begin{itemize} \item select files from working copy \item select files from old revisions \item might be part of Mercurial 1.9 (July) or 2.0 (November) \end{itemize} \end{frame} \begin{frame} File sets give an amazing flexibility. \end{frame} \begin{frame}[fragile]{Working Copy Status} The \cmd{hg status} command lets you select files: \begin{lstlisting} $ hg status M index.html A logo.png $ hg status --added A logo.png \end{lstlisting} How do you see the change to \path{index.html} without seeing the diff of the added \path{logo.png} file? You do: \begin{lstlisting} $ hg diff $(hg status --no-status --modified) \end{lstlisting} With file sets you can do \begin{lstlisting} $ hg diff "set:modified()" \end{lstlisting} and it will work on all platforms. \end{frame} \begin{frame}[fragile]{Working Copy Status} The proposed predicates are: \begin{itemize}[<+->] \item status flags: \cmd{modified()}, \cmd{added()}, \cmd{removed()}, \cmd{deleted()}, \cmd{unknown()}, \cmd{ignored()}, \cmd{clean()} \item copied files: \cmd{copied()} \item tracked files that \emph{would} be ignored: \cmd{ignorable()} \item all tracked files: \cmd{tracked()} \item after a merge: \cmd{conflicted()} and \cmd{not conflicted()} \end{itemize} \end{frame} \begin{frame}[fragile] We can replace the \cmd{find} Unix command: \begin{itemize} \item \cmd{glob(P)} instead of \cmd{find -path P} \item \cmd{regex(P)} instead of \cmd{find -regex P} \end{itemize} Remember that this also works on old revisions: \begin{lstlisting} $ hg status -r 1.0::2.0 "set:glob(src/*.h)" A src/foo.h M src/bar.h \end{lstlisting} This shows that \path{foo.h} is a new header file in version 2.0. \end{frame} \begin{frame} Other \cmd{find}-like predicates will be: \begin{itemize} \item file type: \cmd{executable()}, \cmd{symlink()}, \item permissions: \cmd{perm()}, \cmd{owner()} \item other: \cmd{date()}, \cmd{size()} \end{itemize} \end{frame} \begin{frame} Matching files by content: \begin{itemize} \item \cmd{grep()}: like the Unix \cmd{grep} we all love \item \cmd{contains()}: simple sub-string matching \item \cmd{binary()}, \cmd{text()} \item \cmd{decodes()}: check if file can be decoded with the given character set, such as UTF-8, UTF-16, \dots \item \cmd{eol()}: line-ending type, Unix (\cmd{LF}) or DOS (\cmd{CRLF}) \end{itemize} \end{frame} \begin{frame}[fragile]{Working Copy Predicates} \begin{lstlisting} $ hg status ? logo.png ? index.html $ hg status "set:unknown() and not binary()" ? index.html \end{lstlisting} \end{frame} \begin{frame}[fragile]{Working Copy Predicates} \begin{lstlisting} $ hg status -c 100 "set:decodes('UTF-8')" M plan.txt \end{lstlisting} \end{frame} \begin{frame} Future extensions: \begin{itemize} \item \cmd{magic()}: recognize files based on file content, like the \cmd{file} program in Unix \item \cmd{locked()}: files locked for exclusive access by my \ext{lock} extension \end{itemize} \end{frame} \begin{frame}[fragile]{Implementation} When a revision set is evaluated it is: \begin{description}[<+->] \item[tokenized:] split input into operators, symbols, strings \item[parsed:] build parse tree based on operator precedence \item[optimized:] reorders parse tree to evaluate cheap parts first: \begin{lstlisting} contains("README") and 1.0::1.5 \end{lstlisting} starts with a manifest-based query --- reorder to: \begin{lstlisting} 1.0::1.5 and contains("README") \end{lstlisting} \item[executed:] go through tree and evaluate predicates \end{description} \end{frame} \appendix \newcounter{finalframe} \setcounter{finalframe}{\value{framenumber}} \setcounter{framenumber}{\value{finalframe}} \end{document} % LocalWords: changeset changesets