cdm.py revision bfed486ad8de8b8ebc6345a8e10accae08bf2f45
#
# it under the terms of the GNU General Public License version 2
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
'''workspace extensions for mercurial
This extension contains a number of commands to help you work within
the OpenSolaris consolidations.
Common uses:
Show diffs relative to parent workspace - pdiffs
Check source style rules - nits
Run pre-putback checks - pbchk
Collapse all your changes into a single changeset - recommit'''
#
# NB: This assumes the normal directory structure, with this
#
# If you change that, change this
#
try:
import ConfigParser
if default:
prompt = ' [Y/n]:'
defanswer = 'y'
else:
prompt = ' [y/N]:'
defanswer = 'n'
if not resp:
return default
return True
else:
return False
else:
return default
'''build a list of files in which we're interested
If no files are specified, then we'll default to using
the entire active list.
Returns a dictionary, wherein the keys are cwd-relative file paths,
and the values (when present) are entries from the active list.
Instead of warning the user explicitly about files not in the active
list, we'll attempt to do checks on them.'''
fdict = {}
#
# If the user specified files on the command line, we'll only check
# those files. We won't pull the active list at all. That means we
# won't be smart about skipping deleted files and such, so the user
# needs to be smart enough to not explicitly specify a nonexistent
# file path. Which seems reasonable.
#
if args:
for f in args:
fdict[f] = None
#
# Otherwise, if no files were listed explicitly, we assume that the
# checks should be run on all files in the active list. So we determine
# it here.
#
# Tracking the file paths is a slight optimization, in that multiple
# check functions won't need to derive it themselves. This also dovetails
# nicely with the expectation that explicitly specified files will be
# ${CWD}-relative paths, so the fdict keyspace will be consistent either
# way.
#
else:
return fdict
'''return a function which returns boolean indicating whether a file
should be skipped for CMD.'''
#
# The ignore routines need a canonical path to the file (relative to the
# repo root), whereas the check commands get paths relative to the cwd.
#
# Wrap our argument such that the path is canonified before it is checked.
#
def canonified_check(ignfunc):
def f(path):
return f
ignorefiles = []
if ignorefiles:
return canonified_check(ign)
else:
#
# Adding a reference to WorkSpace from a repo causes a circular reference
# repo <-> WorkSpace.
#
# This prevents repo, WorkSpace and members thereof from being garbage
# collected. Since transactions are aborted when the transaction object
# is collected, and localrepo holds a reference to the most recently created
# transaction, this prevents transactions from cleanly aborting.
#
# Instead, we hold the repo->WorkSpace association in a dictionary, breaking
# that dependence.
#
wslist = {}
'python:hgext_cdm.pbconfirm')
if source == 'push':
return 1
else:
'''list workspace diffs relative to parent workspace
The parent tip is taken to be the latest revision shared between
us and the parent workspace.'''
if diffs:
'''list files changed relative to parent workspace
The parent tip is taken to be the latest revision shared between
us and the parent workspace.'''
wanted = []
if opts['added']:
if opts['modified']:
if opts['removed']:
lst = {}
continue
if elt.is_renamed():
else:
'show all ARC cases in checkin comments'
# We take a set of the appropriate comments to eliminate duplicates.
'show all bug IDs in checkin comments'
'show checkin comments for active files'
'''show renamed active files
Renamed files are shown in the format
newname oldname
One pair per-line.'''
'''check checkin comments for active files
Check that checkin comments conform to O/N rules.'''
'''check for a valid CDDL block in active files
See http://www.opensolaris.org/os/community/on/devref_toc/devref_7/#7_2_3_nonformatting_considerations
for more info.'''
ret = 0
if e and e.is_removed():
continue
continue
elif e and e.is_added():
else:
return ret
'''check for a valid MAPFILE header block in active files
Check that all link-editor mapfiles contain the standard mapfile
header comment directing the reader to the document containing
Solaris object versioning rules (README.mapfile).'''
ret = 0
if e and e.is_removed():
continue
continue
continue
return ret
'''check active files for valid copyrights
Check that all active files have a valid copyright containing the
current year (and *only* the current year).
for more info.'''
ret = 0
if e and e.is_removed():
continue
continue
return ret
'''check active header files conform to O/N rules'''
ret = 0
if e and e.is_removed():
continue
elif not f.endswith('.h'):
continue
continue
return ret
'''check active C source files conform to the C Style Guide
ret = 0
if e and e.is_removed():
continue
continue
continue
return ret
'check active Java source files for common stylistic errors'
ret = 0
if e and e.is_removed():
continue
elif not f.endswith('.java'):
continue
continue
return ret
'''check active files permission - warn +x (execute) mode'''
exeFiles = []
if e and e.is_removed():
continue
continue
'(+x) permission set,\nremove unless intentional:\n')
'''check if .hgtags is active and issue warning
Tag sharing among repositories is restricted to gatekeepers'''
if ".hgtags" in active:
'Only gatekeepers should add or modify such tags.\n'
'Use the following commands to revert these changes:\n'
' hg revert -r%d %s\n'
' hg commit %s\n'
'You should also recommit before integration\n' %
return 1
return 0
'''check if multiple heads (or branches) are present, or if
branch changes are made'''
#
# We care if there's more than one head, and those heads aren't
# identical to the dirstate parents (if they are identical, it's
# an uncommitted merge which mergechk will catch, no need to
# complain twice).
#
return 1
"Only gatekeepers should push new branches.\n"
"Use the following commands to restore the branch name:\n"
" hg branch [-f] default\n"
" hg commit\n"
"You should also recommit before integration\n" %
return 1
for t in branches:
if t == 'default':
continue
"Use the following commands to remove extraneous branches.\n"
" hg branch [-f] default\n"
" hg commit"
"You should also recommit before integration\n")
return 1
return 0
Only works on SWAN.'''
return 0
if not onSWAN():
return 0
bugs = []
# RTI normalizes the gate path for us
'''check source files do not contain SCCS keywords'''
ret = 0
if e and e.is_removed():
continue
continue
return ret
#
# NB:
# There's no reason to hook this up as an invokable command, since
# we have 'hg status', but it must accept the same arguments.
#
'''Warn the user if they have uncommitted changes'''
if st:
return 1
return 0
'''Warn the user if their workspace contains merges'''
if merges:
return 1
return 0
'''Run CMDS (with OPTS) over active files in WS'''
ret = 0
else:
return ret
'''check for stylistic nits in active files
Run cddlchk, copyright, cstyle, hdrchk, jstyle, mapfilechk,
permchk, and keywords checks.'''
cmds = [cdm_cddlchk,
'''pre-putback check all active files
Run cddlchk, comchk, copyright, cstyle, hdrchk, jstyle, mapfilechk,
permchk, tagchk, branchchk, keywords and rtichk checks. Additionally,
warn about uncommitted changes.'''
#
# The current ordering of these is that the commands from cdm_nits
# run first in the same order as they would in cdm_nits. Then the
# pbchk specifics run
#
cmds = [cdm_cddlchk,
'''compact outgoing deltas into a single, conglomerate delta'''
#
# During the course of a recommit, any file bearing a name matching the
# source name of any renamed file will be clobbered by the operation.
#
# As such, we ask the user before proceeding.
#
if bogosity:
"and also present\n"
"in the working directory:\n")
False):
user)
if not message:
if bk.need_backup():
if clearedtags:
if not changedir:
if changedir:
'''run cmd for each active file
cmd can refer to:
$file - active file basename.
$dir - active file dirname.
$filepath - path from workspace root to active file.
$workspace - full path to workspace root.
For example "hg eval 'echo $dir; hg log -l3 $file'" will show the last
the 3 log entries for each active file, preceded by its directory.'''
'''apply cmd to all active files
For example 'hg apply wc -l' outputs a line count of active files.'''
if opts['remain']:
appnd = ' $filepath'
else:
appnd = ' $file'
'''reparent your workspace
Updates the 'default' path.'''
if not p:
try:
try:
except IOError, e:
def backup_name(fullpath):
'''Create a backup directory name based on the specified path.
In most cases this is the basename of the path specified, but
certain cases are handled specially to create meaningful names'''
#
# If a path is 'special', we append the basename of the path to
# the path element preceding the constant, special, part.
#
# Such that for instance:
# /foo/bar/onnv-fixes/usr/closed
# has a backup name of:
# onnv-fixes-closed
#
else:
return fullpath[-1]
'''make backup copies of all workspace changes
Backups will be stored in ~/cdm.backup/<basename of workspace>.'''
else:
'''restore workspace from backup
Restores a workspace from the specified backup directory and generation
(which defaults to the latest).'''
if opts['generation']:
else:
gen = None
'''generate webrev and optionally upload it
This command passes all arguments to webrev script'''
webrev_args = ""
else:
if retval != 0:
return retval - 255
return 0
cmdtable = {
('r', 'remain', None, 'do not change directories')],
'hg apply [-p PARENT] [-r] command...'),
'hg arcs [-p PARENT]'),
'only backup if workspace files are newer')],
'hg backup [-t]'),
'hg branchchk [-p PARENT]'),
'hg bugs [-p PARENT]'),
'hg cddlchk [-p PARENT]'),
('N', 'nocheck', None,
'do not compare comments with databases')],
'hg comchk [-p PARENT]'),
'hg comments [-p PARENT]'),
'hg copyright [-p PARENT]'),
'hg cstyle [-p PARENT]'),
('r', 'remain', None, 'do not change directories')],
'hg eval [-p PARENT] [-r] command...'),
'hg hdrchk [-p PARENT]'),
'hg jstyle [-p PARENT]'),
'hg keywords [-p PARENT]'),
('r', 'removed', None, 'show removed files'),
('a', 'added', None, 'show added files'),
('m', 'modified', None, 'show modified files')],
'hg list [-amrRu] [-p PARENT]'),
'hg mapfilechk [-p PARENT]'),
'hg nits [-p PARENT]'),
('N', 'nocheck', None, 'skip RTI check')],
'hg pbchk [-N] [-p PARENT]'),
'hg permchk [-p PARENT]'),
('a', 'text', None, 'treat all files as text'),
('g', 'git', None, 'use extended git diff format'),
('w', 'ignore-all-space', None,
'ignore white space when comparing lines'),
('b', 'ignore-space-change', None,
'ignore changes in the amount of white space'),
('B', 'ignore-blank-lines', None,
'ignore changes whos lines are all blank'),
('U', 'unified', 3,
'number of lines of context to show'),
('I', 'include', [],
'include names matching the given patterns'),
('X', 'exclude', [],
'exclude names matching the given patterns')],
'hg pdiffs [OPTION...] [-p PARENT] [FILE...]'),
('f', 'force', None, 'force operation'),
('m', 'message', '',
'use <text> as commit message'),
('l', 'logfile', '',
'read commit message from file'),
('u', 'user', '',
'record user as committer')],
'hg recommit [-f] [-p PARENT]'),
'hg renamed [-p PARENT]'),
'hg restore [-g GENERATION] BACKUP'),
('N', 'nocheck', None, 'skip RTI check')],
'hg rtichk [-N] [-p PARENT]'),
'hg tagchk [-p PARENT]'),
('i', 'i', '', 'include file'),
('l', 'l', '', 'extract file list from putback -n'),
('N', 'N', None, 'supress comments'),
('n', 'n', None, 'do not generate webrev'),
('O', 'O', None, 'OpenSolaris mode'),
('o', 'o', '', 'output directory'),
('p', 'p', '', 'use specified parent'),
('t', 't', '', 'upload target'),
('U', 'U', None, 'upload the webrev'),
('w', 'w', '', 'use wx active file')],
'hg webrev [WEBREV_OPTIONS]'),
}