xref: /illumos-gate/usr/src/tools/scripts/webrev.sh (revision 9af2fe54)
148fe8920SMark J. Nelson#!/usr/bin/ksh93 -p
27c478bd9Sstevel@tonic-gate#
37c478bd9Sstevel@tonic-gate# CDDL HEADER START
47c478bd9Sstevel@tonic-gate#
57c478bd9Sstevel@tonic-gate# The contents of this file are subject to the terms of the
6daaffb31Sdp# Common Development and Distribution License (the "License").
7daaffb31Sdp# You may not use this file except in compliance with the License.
87c478bd9Sstevel@tonic-gate#
97c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate# and limitations under the License.
137c478bd9Sstevel@tonic-gate#
147c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate#
207c478bd9Sstevel@tonic-gate# CDDL HEADER END
217c478bd9Sstevel@tonic-gate#
229a70fc3bSMark J. Nelson
237c478bd9Sstevel@tonic-gate#
2478add226Sjmcp# Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
252f54b716SRichard Lowe# Copyright 2008, 2010, Richard Lowe
267646c8f3SMarcel Telka# Copyright 2012 Marcel Telka <marcel@telka.sk>
27d7b56f41SBart Coddens# Copyright 2014 Bart Coddens <bart.coddens@gmail.com>
28b10a3e23SYuri Pankov# Copyright 2017 Nexenta Systems, Inc.
29d8e4595bSJohn Levon# Copyright 2019 Joyent, Inc.
30e2004245SAndrew Stormont# Copyright 2016 RackTop Systems.
31b1374179SBill Sommerfeld# Copyright 2024 Bill Sommerfeld <sommerfeld@hamachi.org>
327ffa1fbeSYuri Pankov#
332f54b716SRichard Lowe
347c478bd9Sstevel@tonic-gate#
35daaffb31Sdp# This script takes a file list and a workspace and builds a set of html files
36daaffb31Sdp# suitable for doing a code review of source changes via a web page.
37daaffb31Sdp# Documentation is available via the manual page, webrev.1, or just
38daaffb31Sdp# type 'webrev -h'.
397c478bd9Sstevel@tonic-gate#
40daaffb31Sdp# Acknowledgements to contributors to webrev are listed in the webrev(1)
41daaffb31Sdp# man page.
427c478bd9Sstevel@tonic-gate#
43daaffb31Sdp
44daaffb31SdpREMOVED_COLOR=brown
45daaffb31SdpCHANGED_COLOR=blue
46daaffb31SdpNEW_COLOR=blue
47daaffb31Sdp
48daaffb31SdpHTML='<?xml version="1.0"?>
49daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
50daaffb31Sdp    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
51daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
52daaffb31Sdp
53daaffb31SdpFRAMEHTML='<?xml version="1.0"?>
54daaffb31Sdp<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
55daaffb31Sdp    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
56daaffb31Sdp<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n'
57daaffb31Sdp
58cac38512SmjnelsonSTDHEAD='<meta http-equiv="cache-control" content="no-cache"></meta>
5948ad9d01SRobert Mustacchi<meta http-equiv="Content-Type" content="text/xhtml;charset=utf-8"></meta>
60cac38512Smjnelson<meta http-equiv="Pragma" content="no-cache"></meta>
61cac38512Smjnelson<meta http-equiv="Expires" content="-1"></meta>
62daaffb31Sdp<!--
63daaffb31Sdp   Note to customizers: the body of the webrev is IDed as SUNWwebrev
64daaffb31Sdp   to allow easy overriding by users of webrev via the userContent.css
65daaffb31Sdp   mechanism available in some browsers.
66daaffb31Sdp
67daaffb31Sdp   For example, to have all "removed" information be red instead of
68daaffb31Sdp   brown, set a rule in your userContent.css file like:
69daaffb31Sdp
70daaffb31Sdp       body#SUNWwebrev span.removed { color: red ! important; }
71daaffb31Sdp-->
72daaffb31Sdp<style type="text/css" media="screen">
73daaffb31Sdpbody {
74daaffb31Sdp    background-color: #eeeeee;
75daaffb31Sdp}
76daaffb31Sdphr {
77daaffb31Sdp    border: none 0;
78daaffb31Sdp    border-top: 1px solid #aaa;
79daaffb31Sdp    height: 1px;
80daaffb31Sdp}
81daaffb31Sdpdiv.summary {
82daaffb31Sdp    font-size: .8em;
83daaffb31Sdp    border-bottom: 1px solid #aaa;
84daaffb31Sdp    padding-left: 1em;
85daaffb31Sdp    padding-right: 1em;
86daaffb31Sdp}
87daaffb31Sdpdiv.summary h2 {
88daaffb31Sdp    margin-bottom: 0.3em;
89daaffb31Sdp}
90daaffb31Sdpdiv.summary table th {
91daaffb31Sdp    text-align: right;
92daaffb31Sdp    vertical-align: top;
93daaffb31Sdp    white-space: nowrap;
94daaffb31Sdp}
95daaffb31Sdpspan.lineschanged {
96daaffb31Sdp    font-size: 0.7em;
97daaffb31Sdp}
98daaffb31Sdpspan.oldmarker {
99daaffb31Sdp    color: red;
100daaffb31Sdp    font-size: large;
101daaffb31Sdp    font-weight: bold;
102daaffb31Sdp}
103daaffb31Sdpspan.newmarker {
104daaffb31Sdp    color: green;
105daaffb31Sdp    font-size: large;
106daaffb31Sdp    font-weight: bold;
107daaffb31Sdp}
108daaffb31Sdpspan.removed {
109daaffb31Sdp    color: brown;
110daaffb31Sdp}
111daaffb31Sdpspan.changed {
112daaffb31Sdp    color: blue;
113daaffb31Sdp}
114daaffb31Sdpspan.new {
115daaffb31Sdp    color: blue;
116daaffb31Sdp    font-weight: bold;
117daaffb31Sdp}
118cdf0c1d5Smjnelsonspan.chmod {
119cdf0c1d5Smjnelson    font-size: 0.7em;
120cdf0c1d5Smjnelson    color: #db7800;
121cdf0c1d5Smjnelson}
122daaffb31Sdpa.print { font-size: x-small; }
123daaffb31Sdpa:hover { background-color: #ffcc99; }
124daaffb31Sdp</style>
125daaffb31Sdp
126daaffb31Sdp<style type="text/css" media="print">
127daaffb31Sdppre { font-size: 0.8em; font-family: courier, monospace; }
128daaffb31Sdpspan.removed { color: #444; font-style: italic }
129daaffb31Sdpspan.changed { font-weight: bold; }
130daaffb31Sdpspan.new { font-weight: bold; }
131daaffb31Sdpspan.newmarker { font-size: 1.2em; font-weight: bold; }
132daaffb31Sdpspan.oldmarker { font-size: 1.2em; font-weight: bold; }
133daaffb31Sdpa.print {display: none}
134daaffb31Sdphr { border: none 0; border-top: 1px solid #aaa; height: 1px; }
135daaffb31Sdp</style>
136daaffb31Sdp'
137daaffb31Sdp
1387c478bd9Sstevel@tonic-gate#
139daaffb31Sdp# UDiffs need a slightly different CSS rule for 'new' items (we don't
140daaffb31Sdp# want them to be bolded as we do in cdiffs or sdiffs).
1417c478bd9Sstevel@tonic-gate#
142daaffb31SdpUDIFFCSS='
143daaffb31Sdp<style type="text/css" media="screen">
144daaffb31Sdpspan.new {
145daaffb31Sdp    color: blue;
146daaffb31Sdp    font-weight: normal;
147daaffb31Sdp}
148daaffb31Sdp</style>
149daaffb31Sdp'
150daaffb31Sdp
1517ffa1fbeSYuri Pankov# CSS for the HTML version of the man pages.
152cec8643bSMichal Nowak# Current version is from mandoc 1.14.5.
1537ffa1fbeSYuri PankovMANCSS='
154cec8643bSMichal Nowak/* $Id: mandoc.css,v 1.45 2019/03/01 10:57:18 schwarze Exp $ */
1556640c13bSYuri Pankov/*
1566640c13bSYuri Pankov * Standard style sheet for mandoc(1) -Thtml and man.cgi(8).
157cec8643bSMichal Nowak *
158cec8643bSMichal Nowak * Written by Ingo Schwarze <schwarze@openbsd.org>.
159cec8643bSMichal Nowak * I place this file into the public domain.
160cec8643bSMichal Nowak * Permission to use, copy, modify, and distribute it for any purpose
161cec8643bSMichal Nowak * with or without fee is hereby granted, without any conditions.
1626640c13bSYuri Pankov */
1636640c13bSYuri Pankov
1646640c13bSYuri Pankov/* Global defaults. */
1656640c13bSYuri Pankov
1666640c13bSYuri Pankovhtml {		max-width: 65em; }
1676640c13bSYuri Pankovbody {		font-family: Helvetica,Arial,sans-serif; }
1686640c13bSYuri Pankovtable {		margin-top: 0em;
169cec8643bSMichal Nowak		margin-bottom: 0em;
170cec8643bSMichal Nowak		border-collapse: collapse; }
171cec8643bSMichal Nowak/* Some browsers set border-color in a browser style for tbody,
172cec8643bSMichal Nowak * but not for table, resulting in inconsistent border styling. */
173cec8643bSMichal Nowaktbody {		border-color: inherit; }
174cec8643bSMichal Nowaktr {		border-color: inherit; }
175cec8643bSMichal Nowaktd {		vertical-align: top;
176cec8643bSMichal Nowak		padding-left: 0.2em;
177cec8643bSMichal Nowak		padding-right: 0.2em;
178cec8643bSMichal Nowak		border-color: inherit; }
1796640c13bSYuri Pankovul, ol, dl {	margin-top: 0em;
1806640c13bSYuri Pankov		margin-bottom: 0em; }
1816640c13bSYuri Pankovli, dt {	margin-top: 1em; }
1826640c13bSYuri Pankov
1836640c13bSYuri Pankov.permalink {	border-bottom: thin dotted;
1846640c13bSYuri Pankov		color: inherit;
1856640c13bSYuri Pankov		font: inherit;
1866640c13bSYuri Pankov		text-decoration: inherit; }
1876640c13bSYuri Pankov* {		clear: both }
1886640c13bSYuri Pankov
1896640c13bSYuri Pankov/* Search form and search results. */
1906640c13bSYuri Pankov
1916640c13bSYuri Pankovfieldset {	border: thin solid silver;
1926640c13bSYuri Pankov		border-radius: 1em;
1936640c13bSYuri Pankov		text-align: center; }
1946640c13bSYuri Pankovinput[name=expr] {
1956640c13bSYuri Pankov		width: 25%; }
1966640c13bSYuri Pankov
1976640c13bSYuri Pankovtable.results {	margin-top: 1em;
1986640c13bSYuri Pankov		margin-left: 2em;
1996640c13bSYuri Pankov		font-size: smaller; }
2006640c13bSYuri Pankov
2016640c13bSYuri Pankov/* Header and footer lines. */
2026640c13bSYuri Pankov
2036640c13bSYuri Pankovtable.head {	width: 100%;
2046640c13bSYuri Pankov		border-bottom: 1px dotted #808080;
2056640c13bSYuri Pankov		margin-bottom: 1em;
2066640c13bSYuri Pankov		font-size: smaller; }
2076640c13bSYuri Pankovtd.head-vol {	text-align: center; }
2086640c13bSYuri Pankovtd.head-rtitle {
2096640c13bSYuri Pankov		text-align: right; }
2106640c13bSYuri Pankov
2116640c13bSYuri Pankovtable.foot {	width: 100%;
2126640c13bSYuri Pankov		border-top: 1px dotted #808080;
2136640c13bSYuri Pankov		margin-top: 1em;
2146640c13bSYuri Pankov		font-size: smaller; }
2156640c13bSYuri Pankovtd.foot-os {	text-align: right; }
2166640c13bSYuri Pankov
2176640c13bSYuri Pankov/* Sections and paragraphs. */
2186640c13bSYuri Pankov
2196640c13bSYuri Pankov.manual-text {
2206640c13bSYuri Pankov		margin-left: 3.8em; }
221cec8643bSMichal Nowak.Nd { }
222cec8643bSMichal Nowaksection.Sh { }
223cec8643bSMichal Nowakh1.Sh {		margin-top: 1.2em;
2246640c13bSYuri Pankov		margin-bottom: 0.6em;
2256640c13bSYuri Pankov		margin-left: -3.2em;
2266640c13bSYuri Pankov		font-size: 110%; }
227cec8643bSMichal Nowaksection.Ss { }
228cec8643bSMichal Nowakh2.Ss {		margin-top: 1.2em;
2296640c13bSYuri Pankov		margin-bottom: 0.6em;
2306640c13bSYuri Pankov		margin-left: -1.2em;
2316640c13bSYuri Pankov		font-size: 105%; }
2326640c13bSYuri Pankov.Pp {		margin: 0.6em 0em; }
2336640c13bSYuri Pankov.Sx { }
2346640c13bSYuri Pankov.Xr { }
2356640c13bSYuri Pankov
2366640c13bSYuri Pankov/* Displays and lists. */
2376640c13bSYuri Pankov
2386640c13bSYuri Pankov.Bd { }
2396640c13bSYuri Pankov.Bd-indent {	margin-left: 3.8em; }
2406640c13bSYuri Pankov
2416640c13bSYuri Pankov.Bl-bullet {	list-style-type: disc;
2426640c13bSYuri Pankov		padding-left: 1em; }
2436640c13bSYuri Pankov.Bl-bullet > li { }
2446640c13bSYuri Pankov.Bl-dash {	list-style-type: none;
2456640c13bSYuri Pankov		padding-left: 0em; }
2466640c13bSYuri Pankov.Bl-dash > li:before {
2476640c13bSYuri Pankov		content: "\2014  "; }
2486640c13bSYuri Pankov.Bl-item {	list-style-type: none;
2496640c13bSYuri Pankov		padding-left: 0em; }
2506640c13bSYuri Pankov.Bl-item > li { }
2516640c13bSYuri Pankov.Bl-compact > li {
2526640c13bSYuri Pankov		margin-top: 0em; }
2536640c13bSYuri Pankov
2546640c13bSYuri Pankov.Bl-enum {	padding-left: 2em; }
2556640c13bSYuri Pankov.Bl-enum > li { }
2566640c13bSYuri Pankov.Bl-compact > li {
2576640c13bSYuri Pankov		margin-top: 0em; }
2586640c13bSYuri Pankov
2596640c13bSYuri Pankov.Bl-diag { }
2606640c13bSYuri Pankov.Bl-diag > dt {
2616640c13bSYuri Pankov		font-style: normal;
2626640c13bSYuri Pankov		font-weight: bold; }
2636640c13bSYuri Pankov.Bl-diag > dd {
2646640c13bSYuri Pankov		margin-left: 0em; }
2656640c13bSYuri Pankov.Bl-hang { }
2666640c13bSYuri Pankov.Bl-hang > dt { }
2676640c13bSYuri Pankov.Bl-hang > dd {
2686640c13bSYuri Pankov		margin-left: 5.5em; }
2696640c13bSYuri Pankov.Bl-inset { }
2706640c13bSYuri Pankov.Bl-inset > dt { }
2716640c13bSYuri Pankov.Bl-inset > dd {
2726640c13bSYuri Pankov		margin-left: 0em; }
2736640c13bSYuri Pankov.Bl-ohang { }
2746640c13bSYuri Pankov.Bl-ohang > dt { }
2756640c13bSYuri Pankov.Bl-ohang > dd {
2766640c13bSYuri Pankov		margin-left: 0em; }
277cec8643bSMichal Nowak.Bl-tag {	margin-top: 0.6em;
278cec8643bSMichal Nowak		margin-left: 5.5em; }
2796640c13bSYuri Pankov.Bl-tag > dt {
2806640c13bSYuri Pankov		float: left;
2816640c13bSYuri Pankov		margin-top: 0em;
2826640c13bSYuri Pankov		margin-left: -5.5em;
283cec8643bSMichal Nowak		padding-right: 0.5em;
2846640c13bSYuri Pankov		vertical-align: top; }
2856640c13bSYuri Pankov.Bl-tag > dd {
2866640c13bSYuri Pankov		clear: right;
2876640c13bSYuri Pankov		width: 100%;
2886640c13bSYuri Pankov		margin-top: 0em;
2896640c13bSYuri Pankov		margin-left: 0em;
290cec8643bSMichal Nowak		margin-bottom: 0.6em;
2916640c13bSYuri Pankov		vertical-align: top;
2926640c13bSYuri Pankov		overflow: auto; }
293cec8643bSMichal Nowak.Bl-compact {	margin-top: 0em; }
294cec8643bSMichal Nowak.Bl-compact > dd {
295cec8643bSMichal Nowak		margin-bottom: 0em; }
2966640c13bSYuri Pankov.Bl-compact > dt {
2976640c13bSYuri Pankov		margin-top: 0em; }
2986640c13bSYuri Pankov
2996640c13bSYuri Pankov.Bl-column { }
3006640c13bSYuri Pankov.Bl-column > tbody > tr { }
3016640c13bSYuri Pankov.Bl-column > tbody > tr > td {
3026640c13bSYuri Pankov		margin-top: 1em; }
3036640c13bSYuri Pankov.Bl-compact > tbody > tr > td {
3046640c13bSYuri Pankov		margin-top: 0em; }
3056640c13bSYuri Pankov
3066640c13bSYuri Pankov.Rs {		font-style: normal;
3076640c13bSYuri Pankov		font-weight: normal; }
3086640c13bSYuri Pankov.RsA { }
3096640c13bSYuri Pankov.RsB {		font-style: italic;
3106640c13bSYuri Pankov		font-weight: normal; }
3116640c13bSYuri Pankov.RsC { }
3126640c13bSYuri Pankov.RsD { }
3136640c13bSYuri Pankov.RsI {		font-style: italic;
3146640c13bSYuri Pankov		font-weight: normal; }
3156640c13bSYuri Pankov.RsJ {		font-style: italic;
3166640c13bSYuri Pankov		font-weight: normal; }
3176640c13bSYuri Pankov.RsN { }
3186640c13bSYuri Pankov.RsO { }
3196640c13bSYuri Pankov.RsP { }
3206640c13bSYuri Pankov.RsQ { }
3216640c13bSYuri Pankov.RsR { }
3226640c13bSYuri Pankov.RsT {		text-decoration: underline; }
3236640c13bSYuri Pankov.RsU { }
3246640c13bSYuri Pankov.RsV { }
3256640c13bSYuri Pankov
3266640c13bSYuri Pankov.eqn { }
327cec8643bSMichal Nowak.tbl td {	vertical-align: middle; }
3286640c13bSYuri Pankov
3296640c13bSYuri Pankov.HP {		margin-left: 3.8em;
3306640c13bSYuri Pankov		text-indent: -3.8em; }
3316640c13bSYuri Pankov
3326640c13bSYuri Pankov/* Semantic markup for command line utilities. */
3336640c13bSYuri Pankov
334a40ea1a7SYuri Pankovtable.Nm { }
3356640c13bSYuri Pankovcode.Nm {	font-style: normal;
3366640c13bSYuri Pankov		font-weight: bold;
3376640c13bSYuri Pankov		font-family: inherit; }
3386640c13bSYuri Pankov.Fl {		font-style: normal;
3396640c13bSYuri Pankov		font-weight: bold;
3406640c13bSYuri Pankov		font-family: inherit; }
3416640c13bSYuri Pankov.Cm {		font-style: normal;
3426640c13bSYuri Pankov		font-weight: bold;
3436640c13bSYuri Pankov		font-family: inherit; }
3446640c13bSYuri Pankov.Ar {		font-style: italic;
3456640c13bSYuri Pankov		font-weight: normal; }
3466640c13bSYuri Pankov.Op {		display: inline; }
3476640c13bSYuri Pankov.Ic {		font-style: normal;
3486640c13bSYuri Pankov		font-weight: bold;
3496640c13bSYuri Pankov		font-family: inherit; }
3506640c13bSYuri Pankov.Ev {		font-style: normal;
3516640c13bSYuri Pankov		font-weight: normal;
3526640c13bSYuri Pankov		font-family: monospace; }
3536640c13bSYuri Pankov.Pa {		font-style: italic;
3546640c13bSYuri Pankov		font-weight: normal; }
3556640c13bSYuri Pankov
3566640c13bSYuri Pankov/* Semantic markup for function libraries. */
3576640c13bSYuri Pankov
3586640c13bSYuri Pankov.Lb { }
3596640c13bSYuri Pankovcode.In {	font-style: normal;
3606640c13bSYuri Pankov		font-weight: bold;
3616640c13bSYuri Pankov		font-family: inherit; }
362a40ea1a7SYuri Pankova.In { }
3636640c13bSYuri Pankov.Fd {		font-style: normal;
3646640c13bSYuri Pankov		font-weight: bold;
3656640c13bSYuri Pankov		font-family: inherit; }
3666640c13bSYuri Pankov.Ft {		font-style: italic;
3676640c13bSYuri Pankov		font-weight: normal; }
3686640c13bSYuri Pankov.Fn {		font-style: normal;
3696640c13bSYuri Pankov		font-weight: bold;
3706640c13bSYuri Pankov		font-family: inherit; }
3716640c13bSYuri Pankov.Fa {		font-style: italic;
3726640c13bSYuri Pankov		font-weight: normal; }
3736640c13bSYuri Pankov.Vt {		font-style: italic;
3746640c13bSYuri Pankov		font-weight: normal; }
3756640c13bSYuri Pankov.Va {		font-style: italic;
3766640c13bSYuri Pankov		font-weight: normal; }
3776640c13bSYuri Pankov.Dv {		font-style: normal;
3786640c13bSYuri Pankov		font-weight: normal;
3796640c13bSYuri Pankov		font-family: monospace; }
3806640c13bSYuri Pankov.Er {		font-style: normal;
3816640c13bSYuri Pankov		font-weight: normal;
3826640c13bSYuri Pankov		font-family: monospace; }
3836640c13bSYuri Pankov
3846640c13bSYuri Pankov/* Various semantic markup. */
3856640c13bSYuri Pankov
3866640c13bSYuri Pankov.An { }
3876640c13bSYuri Pankov.Lk { }
3886640c13bSYuri Pankov.Mt { }
3896640c13bSYuri Pankov.Cd {		font-style: normal;
3906640c13bSYuri Pankov		font-weight: bold;
3916640c13bSYuri Pankov		font-family: inherit; }
3926640c13bSYuri Pankov.Ad {		font-style: italic;
3936640c13bSYuri Pankov		font-weight: normal; }
3946640c13bSYuri Pankov.Ms {		font-style: normal;
3956640c13bSYuri Pankov		font-weight: bold; }
3966640c13bSYuri Pankov.St { }
3976640c13bSYuri Pankov.Ux { }
3986640c13bSYuri Pankov
3996640c13bSYuri Pankov/* Physical markup. */
4006640c13bSYuri Pankov
4016640c13bSYuri Pankov.Bf {		display: inline; }
4026640c13bSYuri Pankov.No {		font-style: normal;
4036640c13bSYuri Pankov		font-weight: normal; }
4046640c13bSYuri Pankov.Em {		font-style: italic;
4056640c13bSYuri Pankov		font-weight: normal; }
4066640c13bSYuri Pankov.Sy {		font-style: normal;
4076640c13bSYuri Pankov		font-weight: bold; }
4086640c13bSYuri Pankov.Li {		font-style: normal;
4096640c13bSYuri Pankov		font-weight: normal;
4106640c13bSYuri Pankov		font-family: monospace; }
4116640c13bSYuri Pankov
412cec8643bSMichal Nowak/* Tooltip support. */
413cec8643bSMichal Nowak
414cec8643bSMichal Nowakh1.Sh, h2.Ss {	position: relative; }
415cec8643bSMichal Nowak.An, .Ar, .Cd, .Cm, .Dv, .Em, .Er, .Ev, .Fa, .Fd, .Fl, .Fn, .Ft,
416cec8643bSMichal Nowak.Ic, code.In, .Lb, .Lk, .Ms, .Mt, .Nd, code.Nm, .Pa, .Rs,
417cec8643bSMichal Nowak.St, .Sx, .Sy, .Va, .Vt, .Xr {
418cec8643bSMichal Nowak		display: inline-block;
419cec8643bSMichal Nowak		position: relative; }
420cec8643bSMichal Nowak
421cec8643bSMichal Nowak.An::before {	content: "An"; }
422cec8643bSMichal Nowak.Ar::before {	content: "Ar"; }
423cec8643bSMichal Nowak.Cd::before {	content: "Cd"; }
424cec8643bSMichal Nowak.Cm::before {	content: "Cm"; }
425cec8643bSMichal Nowak.Dv::before {	content: "Dv"; }
426cec8643bSMichal Nowak.Em::before {	content: "Em"; }
427cec8643bSMichal Nowak.Er::before {	content: "Er"; }
428cec8643bSMichal Nowak.Ev::before {	content: "Ev"; }
429cec8643bSMichal Nowak.Fa::before {	content: "Fa"; }
430cec8643bSMichal Nowak.Fd::before {	content: "Fd"; }
431cec8643bSMichal Nowak.Fl::before {	content: "Fl"; }
432cec8643bSMichal Nowak.Fn::before {	content: "Fn"; }
433cec8643bSMichal Nowak.Ft::before {	content: "Ft"; }
434cec8643bSMichal Nowak.Ic::before {	content: "Ic"; }
435cec8643bSMichal Nowakcode.In::before { content: "In"; }
436cec8643bSMichal Nowak.Lb::before {	content: "Lb"; }
437cec8643bSMichal Nowak.Lk::before {	content: "Lk"; }
438cec8643bSMichal Nowak.Ms::before {	content: "Ms"; }
439cec8643bSMichal Nowak.Mt::before {	content: "Mt"; }
440cec8643bSMichal Nowak.Nd::before {	content: "Nd"; }
441cec8643bSMichal Nowakcode.Nm::before { content: "Nm"; }
442cec8643bSMichal Nowak.Pa::before {	content: "Pa"; }
443cec8643bSMichal Nowak.Rs::before {	content: "Rs"; }
444cec8643bSMichal Nowakh1.Sh::before {	content: "Sh"; }
445cec8643bSMichal Nowakh2.Ss::before {	content: "Ss"; }
446cec8643bSMichal Nowak.St::before {	content: "St"; }
447cec8643bSMichal Nowak.Sx::before {	content: "Sx"; }
448cec8643bSMichal Nowak.Sy::before {	content: "Sy"; }
449cec8643bSMichal Nowak.Va::before {	content: "Va"; }
450cec8643bSMichal Nowak.Vt::before {	content: "Vt"; }
451cec8643bSMichal Nowak.Xr::before {	content: "Xr"; }
452cec8643bSMichal Nowak
453cec8643bSMichal Nowak.An::before, .Ar::before, .Cd::before, .Cm::before,
454cec8643bSMichal Nowak.Dv::before, .Em::before, .Er::before, .Ev::before,
455cec8643bSMichal Nowak.Fa::before, .Fd::before, .Fl::before, .Fn::before, .Ft::before,
456cec8643bSMichal Nowak.Ic::before, code.In::before, .Lb::before, .Lk::before,
457cec8643bSMichal Nowak.Ms::before, .Mt::before, .Nd::before, code.Nm::before,
458cec8643bSMichal Nowak.Pa::before, .Rs::before,
459cec8643bSMichal Nowakh1.Sh::before, h2.Ss::before, .St::before, .Sx::before, .Sy::before,
460cec8643bSMichal Nowak.Va::before, .Vt::before, .Xr::before {
461cec8643bSMichal Nowak		opacity: 0;
462cec8643bSMichal Nowak		transition: .15s ease opacity;
463cec8643bSMichal Nowak		pointer-events: none;
464cec8643bSMichal Nowak		position: absolute;
465cec8643bSMichal Nowak		bottom: 100%;
466cec8643bSMichal Nowak		box-shadow: 0 0 .35em #000;
467cec8643bSMichal Nowak		padding: .15em .25em;
468cec8643bSMichal Nowak		white-space: nowrap;
469cec8643bSMichal Nowak		font-family: Helvetica,Arial,sans-serif;
470cec8643bSMichal Nowak		font-style: normal;
471cec8643bSMichal Nowak		font-weight: bold;
472cec8643bSMichal Nowak		color: black;
473cec8643bSMichal Nowak		background: #fff; }
474cec8643bSMichal Nowak.An:hover::before, .Ar:hover::before, .Cd:hover::before, .Cm:hover::before,
475cec8643bSMichal Nowak.Dv:hover::before, .Em:hover::before, .Er:hover::before, .Ev:hover::before,
476cec8643bSMichal Nowak.Fa:hover::before, .Fd:hover::before, .Fl:hover::before, .Fn:hover::before,
477cec8643bSMichal Nowak.Ft:hover::before, .Ic:hover::before, code.In:hover::before,
478cec8643bSMichal Nowak.Lb:hover::before, .Lk:hover::before, .Ms:hover::before, .Mt:hover::before,
479cec8643bSMichal Nowak.Nd:hover::before, code.Nm:hover::before, .Pa:hover::before,
480cec8643bSMichal Nowak.Rs:hover::before, h1.Sh:hover::before, h2.Ss:hover::before, .St:hover::before,
481cec8643bSMichal Nowak.Sx:hover::before, .Sy:hover::before, .Va:hover::before, .Vt:hover::before,
482cec8643bSMichal Nowak.Xr:hover::before {
483cec8643bSMichal Nowak		opacity: 1;
484cec8643bSMichal Nowak		pointer-events: inherit; }
485cec8643bSMichal Nowak
4866640c13bSYuri Pankov/* Overrides to avoid excessive margins on small devices. */
4876640c13bSYuri Pankov
4886640c13bSYuri Pankov@media (max-width: 37.5em) {
4896640c13bSYuri Pankov.manual-text {
4906640c13bSYuri Pankov		margin-left: 0.5em; }
491cec8643bSMichal Nowakh1.Sh, h2.Ss {	margin-left: 0em; }
4926640c13bSYuri Pankov.Bd-indent {	margin-left: 2em; }
4936640c13bSYuri Pankov.Bl-hang > dd {
4946640c13bSYuri Pankov		margin-left: 2em; }
4956640c13bSYuri Pankov.Bl-tag {	margin-left: 2em; }
4966640c13bSYuri Pankov.Bl-tag > dt {
4976640c13bSYuri Pankov		margin-left: -2em; }
4986640c13bSYuri Pankov.HP {		margin-left: 2em;
4996640c13bSYuri Pankov		text-indent: -2em; }
5006640c13bSYuri Pankov}
5017ffa1fbeSYuri Pankov'
5027ffa1fbeSYuri Pankov
503b0088928SVladimir Kotal#
504b0088928SVladimir Kotal# Display remote target with prefix and trailing slash.
505b0088928SVladimir Kotal#
506b0088928SVladimir Kotalfunction print_upload_header
507b0088928SVladimir Kotal{
508b0088928SVladimir Kotal	typeset -r prefix=$1
509b0088928SVladimir Kotal	typeset display_target
510b0088928SVladimir Kotal
511b0088928SVladimir Kotal	if [[ -z $tflag ]]; then
512b0088928SVladimir Kotal		display_target=${prefix}${remote_target}
513b0088928SVladimir Kotal	else
514b0088928SVladimir Kotal		display_target=${remote_target}
515b0088928SVladimir Kotal	fi
516b0088928SVladimir Kotal
517b0088928SVladimir Kotal	if [[ ${display_target} != */ ]]; then
518b0088928SVladimir Kotal		display_target=${display_target}/
519b0088928SVladimir Kotal	fi
520b0088928SVladimir Kotal
521b0088928SVladimir Kotal	print "      Upload to: ${display_target}\n" \
522b0088928SVladimir Kotal	    "     Uploading: \c"
523b0088928SVladimir Kotal}
524b0088928SVladimir Kotal
525b0088928SVladimir Kotal#
52602d26c39SVladimir Kotal# Upload the webrev via rsync. Return 0 on success, 1 on error.
527b0088928SVladimir Kotal#
528ba44d8a2SVladimir Kotalfunction rsync_upload
52902d26c39SVladimir Kotal{
530b0088928SVladimir Kotal	if (( $# != 2 )); then
531b0088928SVladimir Kotal		print "\nERROR: rsync_upload: wrong usage ($#)"
532b0088928SVladimir Kotal		exit 1
53302d26c39SVladimir Kotal	fi
53402d26c39SVladimir Kotal
535b0088928SVladimir Kotal	typeset -r dst=$1
536b0088928SVladimir Kotal	integer -r print_err_msg=$2
53702d26c39SVladimir Kotal
538b0088928SVladimir Kotal	print_upload_header ${rsync_prefix}
539b0088928SVladimir Kotal	print "rsync ... \c"
5408a34f8dcSVladimir Kotal	typeset -r err_msg=$( $MKTEMP /tmp/rsync_err.XXXXXX )
541b0088928SVladimir Kotal	if [[ -z $err_msg ]]; then
542b0088928SVladimir Kotal		print "\nERROR: rsync_upload: cannot create temporary file"
543b0088928SVladimir Kotal		return 1
544b0088928SVladimir Kotal	fi
545b0088928SVladimir Kotal	#
546b0088928SVladimir Kotal	# The source directory must end with a slash in order to copy just
547b0088928SVladimir Kotal	# directory contents, not the whole directory.
548b0088928SVladimir Kotal	#
549b0088928SVladimir Kotal	typeset src_dir=$WDIR
550b0088928SVladimir Kotal	if [[ ${src_dir} != */ ]]; then
551b0088928SVladimir Kotal		src_dir=${src_dir}/
552b0088928SVladimir Kotal	fi
553b0088928SVladimir Kotal	$RSYNC -r -q ${src_dir} $dst 2>$err_msg
55402d26c39SVladimir Kotal	if (( $? != 0 )); then
555b1374179SBill Sommerfeld		if (( print_err_msg > 0 )); then
556b0088928SVladimir Kotal			print "Failed.\nERROR: rsync failed"
557b0088928SVladimir Kotal			print "src dir: '${src_dir}'\ndst dir: '$dst'"
558b0088928SVladimir Kotal			print "error messages:"
559b0088928SVladimir Kotal			$SED 's/^/> /' $err_msg
560b0088928SVladimir Kotal			rm -f $err_msg
561b0088928SVladimir Kotal		fi
56202d26c39SVladimir Kotal		return 1
56302d26c39SVladimir Kotal	fi
56402d26c39SVladimir Kotal
565b0088928SVladimir Kotal	rm -f $err_msg
56602d26c39SVladimir Kotal	print "Done."
56702d26c39SVladimir Kotal	return 0
56802d26c39SVladimir Kotal}
56902d26c39SVladimir Kotal
570b0088928SVladimir Kotal#
571b0088928SVladimir Kotal# Create directories on remote host using SFTP. Return 0 on success,
572b0088928SVladimir Kotal# 1 on failure.
573b0088928SVladimir Kotal#
574b0088928SVladimir Kotalfunction remote_mkdirs
575b0088928SVladimir Kotal{
576b0088928SVladimir Kotal	typeset -r dir_spec=$1
5779d3952abSVladimir Kotal	typeset -r host_spec=$2
578b0088928SVladimir Kotal
579b0088928SVladimir Kotal	#
580b0088928SVladimir Kotal	# If the supplied path is absolute we assume all directories are
581b0088928SVladimir Kotal	# created, otherwise try to create all directories in the path
582b0088928SVladimir Kotal	# except the last one which will be created by scp.
583b0088928SVladimir Kotal	#
584b0088928SVladimir Kotal	if [[ "${dir_spec}" == */* && "${dir_spec}" != /* ]]; then
585b0088928SVladimir Kotal		print "mkdirs \c"
586b0088928SVladimir Kotal		#
587b0088928SVladimir Kotal		# Remove the last directory from directory specification.
588b0088928SVladimir Kotal		#
589b0088928SVladimir Kotal		typeset -r dirs_mk=${dir_spec%/*}
5908a34f8dcSVladimir Kotal		typeset -r batch_file_mkdir=$( $MKTEMP \
5918a34f8dcSVladimir Kotal		    /tmp/webrev_mkdir.XXXXXX )
592b0088928SVladimir Kotal		if [[ -z $batch_file_mkdir ]]; then
593b0088928SVladimir Kotal			print "\nERROR: remote_mkdirs:" \
594b0088928SVladimir Kotal			    "cannot create temporary file for batch file"
595b0088928SVladimir Kotal			return 1
596b0088928SVladimir Kotal		fi
597b0efaad7SJoshua M. Clulow		OLDIFS=$IFS
598b0efaad7SJoshua M. Clulow		IFS=/
599b0088928SVladimir Kotal		typeset dir
600b0efaad7SJoshua M. Clulow		for dir in ${dirs_mk}; do
601b0088928SVladimir Kotal			#
602b0088928SVladimir Kotal			# Use the '-' prefix to ignore mkdir errors in order
603b0088928SVladimir Kotal			# to avoid an error in case the directory already
604b0088928SVladimir Kotal			# exists. We check the directory with chdir to be sure
605b0088928SVladimir Kotal			# there is one.
606b0088928SVladimir Kotal			#
607b0efaad7SJoshua M. Clulow			print -- "-mkdir ${dir}" >> ${batch_file_mkdir}
608b0efaad7SJoshua M. Clulow			print "chdir ${dir}" >> ${batch_file_mkdir}
609b0efaad7SJoshua M. Clulow		done
610b0efaad7SJoshua M. Clulow		IFS=$OLDIFS
6118a34f8dcSVladimir Kotal		typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX )
612b0088928SVladimir Kotal		if [[ -z ${sftp_err_msg} ]]; then
613b0088928SVladimir Kotal			print "\nERROR: remote_mkdirs:" \
614b0088928SVladimir Kotal			    "cannot create temporary file for error messages"
615b0088928SVladimir Kotal			return 1
616b0088928SVladimir Kotal		fi
617b0088928SVladimir Kotal		$SFTP -b ${batch_file_mkdir} ${host_spec} 2>${sftp_err_msg} 1>&2
618b0088928SVladimir Kotal		if (( $? != 0 )); then
619b0088928SVladimir Kotal			print "\nERROR: failed to create remote directories"
620b0088928SVladimir Kotal			print "error messages:"
621b0088928SVladimir Kotal			$SED 's/^/> /' ${sftp_err_msg}
622b0088928SVladimir Kotal			rm -f ${sftp_err_msg} ${batch_file_mkdir}
623b0088928SVladimir Kotal			return 1
624b0088928SVladimir Kotal		fi
625b0088928SVladimir Kotal		rm -f ${sftp_err_msg} ${batch_file_mkdir}
626b0088928SVladimir Kotal	fi
627b0088928SVladimir Kotal
628b0088928SVladimir Kotal	return 0
629b0088928SVladimir Kotal}
630b0088928SVladimir Kotal
631b0088928SVladimir Kotal#
63202d26c39SVladimir Kotal# Upload the webrev via SSH. Return 0 on success, 1 on error.
633b0088928SVladimir Kotal#
634ba44d8a2SVladimir Kotalfunction ssh_upload
63502d26c39SVladimir Kotal{
63602d26c39SVladimir Kotal	if (( $# != 1 )); then
637b0088928SVladimir Kotal		print "\nERROR: ssh_upload: wrong number of arguments"
638b0088928SVladimir Kotal		exit 1
63902d26c39SVladimir Kotal	fi
64002d26c39SVladimir Kotal
64102d26c39SVladimir Kotal	typeset dst=$1
64202d26c39SVladimir Kotal	typeset -r host_spec=${dst%%:*}
643ba44d8a2SVladimir Kotal	typeset -r dir_spec=${dst#*:}
64402d26c39SVladimir Kotal
645b0088928SVladimir Kotal	#
646b0088928SVladimir Kotal	# Display the upload information before calling delete_webrev
647b0088928SVladimir Kotal	# because it will also print its progress.
648b0088928SVladimir Kotal	#
649b0088928SVladimir Kotal	print_upload_header ${ssh_prefix}
650b0088928SVladimir Kotal
651b0088928SVladimir Kotal	#
652b0088928SVladimir Kotal	# If the deletion was explicitly requested there is no need
653b0088928SVladimir Kotal	# to perform it again.
654b0088928SVladimir Kotal	#
655ba44d8a2SVladimir Kotal	if [[ -z $Dflag ]]; then
656b0088928SVladimir Kotal		#
657b0088928SVladimir Kotal		# We do not care about return value because this might be
658b0088928SVladimir Kotal		# the first time this directory is uploaded.
659b0088928SVladimir Kotal		#
660ba44d8a2SVladimir Kotal		delete_webrev 0
66102d26c39SVladimir Kotal	fi
66202d26c39SVladimir Kotal
663b0088928SVladimir Kotal	#
664b0088928SVladimir Kotal	# Create remote directories. Any error reporting will be done
665b0088928SVladimir Kotal	# in remote_mkdirs function.
666b0088928SVladimir Kotal	#
6679d3952abSVladimir Kotal	remote_mkdirs ${dir_spec} ${host_spec}
668b0088928SVladimir Kotal	if (( $? != 0 )); then
669b0088928SVladimir Kotal		return 1
67002d26c39SVladimir Kotal	fi
67102d26c39SVladimir Kotal
672b0088928SVladimir Kotal	print "upload ... \c"
6738a34f8dcSVladimir Kotal	typeset -r scp_err_msg=$( $MKTEMP /tmp/scp_err.XXXXXX )
674b0088928SVladimir Kotal	if [[ -z ${scp_err_msg} ]]; then
675b0088928SVladimir Kotal		print "\nERROR: ssh_upload:" \
676b0088928SVladimir Kotal		    "cannot create temporary file for error messages"
677b0088928SVladimir Kotal		return 1
678b0088928SVladimir Kotal	fi
67902d26c39SVladimir Kotal	$SCP -q -C -B -o PreferredAuthentications=publickey -r \
680b0088928SVladimir Kotal		$WDIR $dst 2>${scp_err_msg}
68102d26c39SVladimir Kotal	if (( $? != 0 )); then
682b0088928SVladimir Kotal		print "Failed.\nERROR: scp failed"
683b0088928SVladimir Kotal		print "src dir: '$WDIR'\ndst dir: '$dst'"
684b0088928SVladimir Kotal		print "error messages:"
685b0088928SVladimir Kotal		$SED 's/^/> /' ${scp_err_msg}
686b0088928SVladimir Kotal		rm -f ${scp_err_msg}
68702d26c39SVladimir Kotal		return 1
68802d26c39SVladimir Kotal	fi
68902d26c39SVladimir Kotal
690b0088928SVladimir Kotal	rm -f ${scp_err_msg}
69102d26c39SVladimir Kotal	print "Done."
69202d26c39SVladimir Kotal	return 0
69302d26c39SVladimir Kotal}
69402d26c39SVladimir Kotal
695ba44d8a2SVladimir Kotal#
696ba44d8a2SVladimir Kotal# Delete webrev at remote site. Return 0 on success, 1 or exit code from sftp
697b0088928SVladimir Kotal# on failure. If first argument is 1 then perform the check of sftp return
698b0088928SVladimir Kotal# value otherwise ignore it. If second argument is present it means this run
699b0088928SVladimir Kotal# only performs deletion.
700ba44d8a2SVladimir Kotal#
701ba44d8a2SVladimir Kotalfunction delete_webrev
702ba44d8a2SVladimir Kotal{
703b0088928SVladimir Kotal	if (( $# < 1 )); then
704b0088928SVladimir Kotal		print "delete_webrev: wrong number of arguments"
705b0088928SVladimir Kotal		exit 1
706b0088928SVladimir Kotal	fi
707b0088928SVladimir Kotal
708b0088928SVladimir Kotal	integer -r check=$1
709b0088928SVladimir Kotal	integer delete_only=0
710b0088928SVladimir Kotal	if (( $# == 2 )); then
711b0088928SVladimir Kotal		delete_only=1
712ba44d8a2SVladimir Kotal	fi
713ba44d8a2SVladimir Kotal
714b0088928SVladimir Kotal	#
715ba44d8a2SVladimir Kotal	# Strip the transport specification part of remote target first.
716b0088928SVladimir Kotal	#
717ba44d8a2SVladimir Kotal	typeset -r stripped_target=${remote_target##*://}
718ba44d8a2SVladimir Kotal	typeset -r host_spec=${stripped_target%%:*}
719ba44d8a2SVladimir Kotal	typeset -r dir_spec=${stripped_target#*:}
720ba44d8a2SVladimir Kotal	typeset dir_rm
721ba44d8a2SVladimir Kotal
722b0088928SVladimir Kotal	#
723ba44d8a2SVladimir Kotal	# Do not accept an absolute path.
724b0088928SVladimir Kotal	#
725ba44d8a2SVladimir Kotal	if [[ ${dir_spec} == /* ]]; then
726ba44d8a2SVladimir Kotal		return 1
727ba44d8a2SVladimir Kotal	fi
728ba44d8a2SVladimir Kotal
729b0088928SVladimir Kotal	#
730ba44d8a2SVladimir Kotal	# Strip the ending slash.
731b0088928SVladimir Kotal	#
732ba44d8a2SVladimir Kotal	if [[ ${dir_spec} == */ ]]; then
733ba44d8a2SVladimir Kotal		dir_rm=${dir_spec%%/}
734ba44d8a2SVladimir Kotal	else
735ba44d8a2SVladimir Kotal		dir_rm=${dir_spec}
736ba44d8a2SVladimir Kotal	fi
737ba44d8a2SVladimir Kotal
738b1374179SBill Sommerfeld	if (( delete_only > 0 )); then
739b0088928SVladimir Kotal		print "       Removing: \c"
740b0088928SVladimir Kotal	else
741b0088928SVladimir Kotal		print "rmdir \c"
742b0088928SVladimir Kotal	fi
743ba44d8a2SVladimir Kotal	if [[ -z "$dir_rm" ]]; then
744b0088928SVladimir Kotal		print "\nERROR: empty directory for removal"
745ba44d8a2SVladimir Kotal		return 1
746ba44d8a2SVladimir Kotal	fi
747ba44d8a2SVladimir Kotal
748b0088928SVladimir Kotal	#
749ba44d8a2SVladimir Kotal	# Prepare batch file.
750b0088928SVladimir Kotal	#
7518a34f8dcSVladimir Kotal	typeset -r batch_file_rm=$( $MKTEMP /tmp/webrev_remove.XXXXXX )
752ba44d8a2SVladimir Kotal	if [[ -z $batch_file_rm ]]; then
753b0088928SVladimir Kotal		print "\nERROR: delete_webrev: cannot create temporary file"
754ba44d8a2SVladimir Kotal		return 1
755ba44d8a2SVladimir Kotal	fi
756ba44d8a2SVladimir Kotal	print "rename $dir_rm $TRASH_DIR/removed.$$" > $batch_file_rm
757ba44d8a2SVladimir Kotal
758b0088928SVladimir Kotal	#
759ba44d8a2SVladimir Kotal	# Perform remote deletion and remove the batch file.
760b0088928SVladimir Kotal	#
7618a34f8dcSVladimir Kotal	typeset -r sftp_err_msg=$( $MKTEMP /tmp/webrev_scp_err.XXXXXX )
762b0088928SVladimir Kotal	if [[ -z ${sftp_err_msg} ]]; then
763b0088928SVladimir Kotal		print "\nERROR: delete_webrev:" \
764b0088928SVladimir Kotal		    "cannot create temporary file for error messages"
765b0088928SVladimir Kotal		return 1
766b0088928SVladimir Kotal	fi
767b0088928SVladimir Kotal	$SFTP -b $batch_file_rm $host_spec 2>${sftp_err_msg} 1>&2
768ba44d8a2SVladimir Kotal	integer -r ret=$?
769ba44d8a2SVladimir Kotal	rm -f $batch_file_rm
770b1374179SBill Sommerfeld	if (( ret != 0 && check > 0 )); then
771b0088928SVladimir Kotal		print "Failed.\nERROR: failed to remove remote directories"
772b0088928SVladimir Kotal		print "error messages:"
773b0088928SVladimir Kotal		$SED 's/^/> /' ${sftp_err_msg}
774b0088928SVladimir Kotal		rm -f ${sftp_err_msg}
775ba44d8a2SVladimir Kotal		return $ret
776ba44d8a2SVladimir Kotal	fi
777b0088928SVladimir Kotal	rm -f ${sftp_err_msg}
778b1374179SBill Sommerfeld	if (( delete_only > 0 )); then
779b0088928SVladimir Kotal		print "Done."
780b0088928SVladimir Kotal	fi
781ba44d8a2SVladimir Kotal
782ba44d8a2SVladimir Kotal	return 0
783ba44d8a2SVladimir Kotal}
784ba44d8a2SVladimir Kotal
78502d26c39SVladimir Kotal#
78602d26c39SVladimir Kotal# Upload webrev to remote site
78702d26c39SVladimir Kotal#
788ba44d8a2SVladimir Kotalfunction upload_webrev
78902d26c39SVladimir Kotal{
790b0088928SVladimir Kotal	integer ret
79102d26c39SVladimir Kotal
79202d26c39SVladimir Kotal	if [[ ! -d "$WDIR" ]]; then
793b0088928SVladimir Kotal		print "\nERROR: webrev directory '$WDIR' does not exist"
79402d26c39SVladimir Kotal		return 1
79502d26c39SVladimir Kotal	fi
79602d26c39SVladimir Kotal
797b0088928SVladimir Kotal	#
79802d26c39SVladimir Kotal	# Perform a late check to make sure we do not upload closed source
79902d26c39SVladimir Kotal	# to remote target when -n is used. If the user used custom remote
80002d26c39SVladimir Kotal	# target he probably knows what he is doing.
801b0088928SVladimir Kotal	#
80202d26c39SVladimir Kotal	if [[ -n $nflag && -z $tflag ]]; then
803ba44d8a2SVladimir Kotal		$FIND $WDIR -type d -name closed \
80402d26c39SVladimir Kotal			| $GREP closed >/dev/null
80502d26c39SVladimir Kotal		if (( $? == 0 )); then
806b0088928SVladimir Kotal			print "\nERROR: directory '$WDIR' contains" \
807b0088928SVladimir Kotal			    "\"closed\" directory"
80802d26c39SVladimir Kotal			return 1
80902d26c39SVladimir Kotal		fi
81002d26c39SVladimir Kotal	fi
81102d26c39SVladimir Kotal
812b0088928SVladimir Kotal
813b0088928SVladimir Kotal	#
814b0088928SVladimir Kotal	# We have the URI for remote destination now so let's start the upload.
815b0088928SVladimir Kotal	#
81602d26c39SVladimir Kotal	if [[ -n $tflag ]]; then
81702d26c39SVladimir Kotal		if [[ "${remote_target}" == ${rsync_prefix}?* ]]; then
818b0088928SVladimir Kotal			rsync_upload ${remote_target##$rsync_prefix} 1
819b0088928SVladimir Kotal			ret=$?
820b0088928SVladimir Kotal			return $ret
82102d26c39SVladimir Kotal		elif [[ "${remote_target}" == ${ssh_prefix}?* ]]; then
82202d26c39SVladimir Kotal			ssh_upload ${remote_target##$ssh_prefix}
823b0088928SVladimir Kotal			ret=$?
824b0088928SVladimir Kotal			return $ret
82502d26c39SVladimir Kotal		fi
82602d26c39SVladimir Kotal	else
827b0088928SVladimir Kotal		#
828b0088928SVladimir Kotal		# Try rsync first and fallback to SSH in case it fails.
829b0088928SVladimir Kotal		#
830b0088928SVladimir Kotal		rsync_upload ${remote_target} 0
831b0088928SVladimir Kotal		ret=$?
832b1374179SBill Sommerfeld		if (( ret != 0 )); then
833b0088928SVladimir Kotal			print "Failed. (falling back to SSH)"
834ba44d8a2SVladimir Kotal			ssh_upload ${remote_target}
835b0088928SVladimir Kotal			ret=$?
83602d26c39SVladimir Kotal		fi
837b0088928SVladimir Kotal		return $ret
83802d26c39SVladimir Kotal	fi
83902d26c39SVladimir Kotal}
84002d26c39SVladimir Kotal
841371d72daSLubomir Sedlacik#
842371d72daSLubomir Sedlacik# input_cmd | url_encode | output_cmd
843371d72daSLubomir Sedlacik#
844371d72daSLubomir Sedlacik# URL-encode (percent-encode) reserved characters as defined in RFC 3986.
845371d72daSLubomir Sedlacik#
846371d72daSLubomir Sedlacik# Reserved characters are: :/?#[]@!$&'()*+,;=
847371d72daSLubomir Sedlacik#
848371d72daSLubomir Sedlacik# While not a reserved character itself, percent '%' is reserved by definition
849371d72daSLubomir Sedlacik# so encode it first to avoid recursive transformation, and skip '/' which is
850371d72daSLubomir Sedlacik# a path delimiter.
851371d72daSLubomir Sedlacik#
85225cc4e45SVladimir Kotal# The quotation character is deliberately not escaped in order to make
85325cc4e45SVladimir Kotal# the substitution work with GNU sed.
85425cc4e45SVladimir Kotal#
855371d72daSLubomir Sedlacikfunction url_encode
856371d72daSLubomir Sedlacik{
857b0088928SVladimir Kotal	$SED -e "s|%|%25|g" -e "s|:|%3A|g" -e "s|\&|%26|g" \
858371d72daSLubomir Sedlacik	    -e "s|?|%3F|g" -e "s|#|%23|g" -e "s|\[|%5B|g" \
859371d72daSLubomir Sedlacik	    -e "s|*|%2A|g" -e "s|@|%40|g" -e "s|\!|%21|g" \
860371d72daSLubomir Sedlacik	    -e "s|=|%3D|g" -e "s|;|%3B|g" -e "s|\]|%5D|g" \
86125cc4e45SVladimir Kotal	    -e "s|(|%28|g" -e "s|)|%29|g" -e "s|'|%27|g" \
862371d72daSLubomir Sedlacik	    -e "s|+|%2B|g" -e "s|\,|%2C|g" -e "s|\\\$|%24|g"
863371d72daSLubomir Sedlacik}
864371d72daSLubomir Sedlacik
8657c478bd9Sstevel@tonic-gate#
866daaffb31Sdp# input_cmd | html_quote | output_cmd
867daaffb31Sdp# or
868daaffb31Sdp# html_quote filename | output_cmd
8697c478bd9Sstevel@tonic-gate#
870daaffb31Sdp# Make a piece of source code safe for display in an HTML <pre> block.
8717c478bd9Sstevel@tonic-gate#
872daaffb31Sdphtml_quote()
873daaffb31Sdp{
874b0088928SVladimir Kotal	$SED -e "s/&/\&amp;/g" -e "s/</\&lt;/g" -e "s/>/\&gt;/g" "$@" | expand
875daaffb31Sdp}
876daaffb31Sdp
877cec8643bSMichal Nowak#
8788bcea973SRichard Lowe# Trim a digest-style revision to a conventionally readable yet useful length
8798bcea973SRichard Lowe#
8808bcea973SRichard Lowetrim_digest()
8818bcea973SRichard Lowe{
8828bcea973SRichard Lowe	typeset digest=$1
8838bcea973SRichard Lowe
8848bcea973SRichard Lowe	echo $digest | $SED -e 's/\([0-9a-f]\{12\}\).*/\1/'
8858bcea973SRichard Lowe}
8868bcea973SRichard Lowe
8877c478bd9Sstevel@tonic-gate#
8880fd2682eSMark J. Nelson# input_cmd | its2url | output_cmd
8897c478bd9Sstevel@tonic-gate#
8900fd2682eSMark J. Nelson# Scan for information tracking system references and insert <a> links to the
8910fd2682eSMark J. Nelson# relevant databases.
8927c478bd9Sstevel@tonic-gate#
8930fd2682eSMark J. Nelsonits2url()
894daaffb31Sdp{
8950fd2682eSMark J. Nelson	$SED -f ${its_sed_script}
896daaffb31Sdp}
897daaffb31Sdp
8987c478bd9Sstevel@tonic-gate#
899daaffb31Sdp# strip_unchanged <infile> | output_cmd
9007c478bd9Sstevel@tonic-gate#
901daaffb31Sdp# Removes chunks of sdiff documents that have not changed. This makes it
902daaffb31Sdp# easier for a code reviewer to find the bits that have changed.
9037c478bd9Sstevel@tonic-gate#
904daaffb31Sdp# Deleted lines of text are replaced by a horizontal rule. Some
905daaffb31Sdp# identical lines are retained before and after the changed lines to
906daaffb31Sdp# provide some context.  The number of these lines is controlled by the
907cdf0c1d5Smjnelson# variable C in the $AWK script below.
9087c478bd9Sstevel@tonic-gate#
909daaffb31Sdp# The script detects changed lines as any line that has a "<span class="
910daaffb31Sdp# string embedded (unchanged lines have no particular class and are not
911daaffb31Sdp# part of a <span>).  Blank lines (without a sequence number) are also
912daaffb31Sdp# detected since they flag lines that have been inserted or deleted.
9137c478bd9Sstevel@tonic-gate#
914daaffb31Sdpstrip_unchanged()
915daaffb31Sdp{
916cdf0c1d5Smjnelson	$AWK '
917daaffb31Sdp	BEGIN	{ C = c = 20 }
918cdf0c1d5Smjnelson	NF == 0 || /<span class="/ {
919daaffb31Sdp		if (c > C) {
920daaffb31Sdp			c -= C
921daaffb31Sdp			inx = 0
922daaffb31Sdp			if (c > C) {
923cac38512Smjnelson				print "\n</pre><hr></hr><pre>"
924daaffb31Sdp				inx = c % C
925daaffb31Sdp				c = C
926daaffb31Sdp			}
9277c478bd9Sstevel@tonic-gate
928daaffb31Sdp			for (i = 0; i < c; i++)
929daaffb31Sdp				print ln[(inx + i) % C]
930daaffb31Sdp		}
931daaffb31Sdp		c = 0;
932daaffb31Sdp		print
933daaffb31Sdp		next
934daaffb31Sdp	}
935daaffb31Sdp	{	if (c >= C) {
936daaffb31Sdp			ln[c % C] = $0
937daaffb31Sdp			c++;
938daaffb31Sdp			next;
939daaffb31Sdp		}
940daaffb31Sdp		c++;
941daaffb31Sdp		print
942daaffb31Sdp	}
943cac38512Smjnelson	END	{ if (c > (C * 2)) print "\n</pre><hr></hr>" }
9447c478bd9Sstevel@tonic-gate
945daaffb31Sdp	' $1
9467c478bd9Sstevel@tonic-gate}
9477c478bd9Sstevel@tonic-gate
9487c478bd9Sstevel@tonic-gate#
949daaffb31Sdp# sdiff_to_html
9507c478bd9Sstevel@tonic-gate#
951daaffb31Sdp# This function takes two files as arguments, obtains their diff, and
952daaffb31Sdp# processes the diff output to present the files as an HTML document with
953daaffb31Sdp# the files displayed side-by-side, differences shown in color.  It also
954daaffb31Sdp# takes a delta comment, rendered as an HTML snippet, as the third
955daaffb31Sdp# argument.  The function takes two files as arguments, then the name of
956daaffb31Sdp# file, the path, and the comment.  The HTML will be delivered on stdout,
957daaffb31Sdp# e.g.
9587c478bd9Sstevel@tonic-gate#
959daaffb31Sdp#   $ sdiff_to_html old/usr/src/tools/scripts/webrev.sh \
960daaffb31Sdp#         new/usr/src/tools/scripts/webrev.sh \
961daaffb31Sdp#         webrev.sh usr/src/tools/scripts \
962daaffb31Sdp#         '<a href="http://monaco.sfbay.sun.com/detail.jsp?cr=1234567">
963daaffb31Sdp#          1234567</a> my bugid' > <file>.html
9647c478bd9Sstevel@tonic-gate#
965daaffb31Sdp# framed_sdiff() is then called which creates $2.frames.html
966daaffb31Sdp# in the webrev tree.
9677c478bd9Sstevel@tonic-gate#
968daaffb31Sdp# FYI: This function is rather unusual in its use of awk.  The initial
969daaffb31Sdp# diff run produces conventional diff output showing changed lines mixed
970daaffb31Sdp# with editing codes.  The changed lines are ignored - we're interested in
971daaffb31Sdp# the editing codes, e.g.
9727c478bd9Sstevel@tonic-gate#
9737c478bd9Sstevel@tonic-gate#      8c8
9747c478bd9Sstevel@tonic-gate#      57a61
9757c478bd9Sstevel@tonic-gate#      63c66,76
9767c478bd9Sstevel@tonic-gate#      68,93d80
9777c478bd9Sstevel@tonic-gate#      106d90
9787c478bd9Sstevel@tonic-gate#      108,110d91
9797c478bd9Sstevel@tonic-gate#
980daaffb31Sdp#  These editing codes are parsed by the awk script and used to generate
981daaffb31Sdp#  another awk script that generates HTML, e.g the above lines would turn
982daaffb31Sdp#  into something like this:
9837c478bd9Sstevel@tonic-gate#
9847c478bd9Sstevel@tonic-gate#      BEGIN { printf "<pre>\n" }
9857c478bd9Sstevel@tonic-gate#      function sp(n) {for (i=0;i<n;i++)printf "\n"}
986daaffb31Sdp#      function wl(n) {printf "<font color=%s>%4d %s </font>\n", n, NR, $0}
9877c478bd9Sstevel@tonic-gate#      NR==8           {wl("#7A7ADD");next}
9887c478bd9Sstevel@tonic-gate#      NR==54          {wl("#7A7ADD");sp(3);next}
9897c478bd9Sstevel@tonic-gate#      NR==56          {wl("#7A7ADD");next}
9907c478bd9Sstevel@tonic-gate#      NR==57          {wl("black");printf "\n"; next}
9917c478bd9Sstevel@tonic-gate#        :               :
9927c478bd9Sstevel@tonic-gate#
993daaffb31Sdp#  This script is then run on the original source file to generate the
994daaffb31Sdp#  HTML that corresponds to the source file.
9957c478bd9Sstevel@tonic-gate#
996daaffb31Sdp#  The two HTML files are then combined into a single piece of HTML that
997daaffb31Sdp#  uses an HTML table construct to present the files side by side.  You'll
998daaffb31Sdp#  notice that the changes are color-coded:
9997c478bd9Sstevel@tonic-gate#
10007c478bd9Sstevel@tonic-gate#   black     - unchanged lines
10017c478bd9Sstevel@tonic-gate#   blue      - changed lines
10027c478bd9Sstevel@tonic-gate#   bold blue - new lines
10037c478bd9Sstevel@tonic-gate#   brown     - deleted lines
10047c478bd9Sstevel@tonic-gate#
1005daaffb31Sdp#  Blank lines are inserted in each file to keep unchanged lines in sync
1006daaffb31Sdp#  (side-by-side).  This format is familiar to users of sdiff(1) or
1007daaffb31Sdp#  Teamware's filemerge tool.
10087c478bd9Sstevel@tonic-gate#
1009daaffb31Sdpsdiff_to_html()
1010daaffb31Sdp{
1011daaffb31Sdp	diff -b $1 $2 > /tmp/$$.diffs
10127c478bd9Sstevel@tonic-gate
1013daaffb31Sdp	TNAME=$3
1014daaffb31Sdp	TPATH=$4
1015daaffb31Sdp	COMMENT=$5
10167c478bd9Sstevel@tonic-gate
1017daaffb31Sdp	#
1018daaffb31Sdp	#  Now we have the diffs, generate the HTML for the old file.
1019daaffb31Sdp	#
1020cdf0c1d5Smjnelson	$AWK '
1021daaffb31Sdp	BEGIN	{
1022daaffb31Sdp		printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
1023daaffb31Sdp		printf "function removed() "
1024daaffb31Sdp		printf "{printf \"<span class=\\\"removed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
1025daaffb31Sdp		printf "function changed() "
1026daaffb31Sdp		printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
1027daaffb31Sdp		printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
10287c478bd9Sstevel@tonic-gate}
1029daaffb31Sdp	/^</	{next}
1030daaffb31Sdp	/^>/	{next}
1031daaffb31Sdp	/^---/	{next}
1032daaffb31Sdp
1033daaffb31Sdp	{
10347c478bd9Sstevel@tonic-gate	split($1, a, /[cad]/) ;
10357c478bd9Sstevel@tonic-gate	if (index($1, "a")) {
10367c478bd9Sstevel@tonic-gate		if (a[1] == 0) {
10377c478bd9Sstevel@tonic-gate			n = split(a[2], r, /,/);
10387c478bd9Sstevel@tonic-gate			if (n == 1)
10397c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(1)}\n"
10407c478bd9Sstevel@tonic-gate			else
10417c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(%d)}\n",\
10427c478bd9Sstevel@tonic-gate				(r[2] - r[1]) + 1
10437c478bd9Sstevel@tonic-gate			next
10447c478bd9Sstevel@tonic-gate		}
10457c478bd9Sstevel@tonic-gate
10467c478bd9Sstevel@tonic-gate		printf "NR==%s\t\t{", a[1]
10477c478bd9Sstevel@tonic-gate		n = split(a[2], r, /,/);
10487c478bd9Sstevel@tonic-gate		s = r[1];
10497c478bd9Sstevel@tonic-gate		if (n == 1)
10507c478bd9Sstevel@tonic-gate			printf "bl();printf \"\\n\"; next}\n"
10517c478bd9Sstevel@tonic-gate		else {
10527c478bd9Sstevel@tonic-gate			n = r[2] - r[1]
10537c478bd9Sstevel@tonic-gate			printf "bl();sp(%d);next}\n",\
10547c478bd9Sstevel@tonic-gate			(r[2] - r[1]) + 1
10557c478bd9Sstevel@tonic-gate		}
1056daaffb31Sdp		next
10577c478bd9Sstevel@tonic-gate	}
10587c478bd9Sstevel@tonic-gate	if (index($1, "d")) {
10597c478bd9Sstevel@tonic-gate		n = split(a[1], r, /,/);
10607c478bd9Sstevel@tonic-gate		n1 = r[1]
10617c478bd9Sstevel@tonic-gate		n2 = r[2]
10627c478bd9Sstevel@tonic-gate		if (n == 1)
1063daaffb31Sdp			printf "NR==%s\t\t{removed(); next}\n" , n1
10647c478bd9Sstevel@tonic-gate		else
1065daaffb31Sdp			printf "NR==%s,NR==%s\t{removed(); next}\n" , n1, n2
1066daaffb31Sdp		next
10677c478bd9Sstevel@tonic-gate	}
10687c478bd9Sstevel@tonic-gate	if (index($1, "c")) {
10697c478bd9Sstevel@tonic-gate		n = split(a[1], r, /,/);
10707c478bd9Sstevel@tonic-gate		n1 = r[1]
10717c478bd9Sstevel@tonic-gate		n2 = r[2]
10727c478bd9Sstevel@tonic-gate		final = n2
10737c478bd9Sstevel@tonic-gate		d1 = 0
10747c478bd9Sstevel@tonic-gate		if (n == 1)
1075daaffb31Sdp			printf "NR==%s\t\t{changed();" , n1
10767c478bd9Sstevel@tonic-gate		else {
10777c478bd9Sstevel@tonic-gate			d1 = n2 - n1
1078daaffb31Sdp			printf "NR==%s,NR==%s\t{changed();" , n1, n2
10797c478bd9Sstevel@tonic-gate		}
10807c478bd9Sstevel@tonic-gate		m = split(a[2], r, /,/);
10817c478bd9Sstevel@tonic-gate		n1 = r[1]
10827c478bd9Sstevel@tonic-gate		n2 = r[2]
10837c478bd9Sstevel@tonic-gate		if (m > 1) {
10847c478bd9Sstevel@tonic-gate			d2  = n2 - n1
10857c478bd9Sstevel@tonic-gate			if (d2 > d1) {
10867c478bd9Sstevel@tonic-gate				if (n > 1) printf "if (NR==%d)", final
10877c478bd9Sstevel@tonic-gate				printf "sp(%d);", d2 - d1
10887c478bd9Sstevel@tonic-gate			}
10897c478bd9Sstevel@tonic-gate		}
10907c478bd9Sstevel@tonic-gate		printf "next}\n" ;
1091daaffb31Sdp
1092daaffb31Sdp		next
1093daaffb31Sdp	}
10947c478bd9Sstevel@tonic-gate	}
10957c478bd9Sstevel@tonic-gate
1096daaffb31Sdp	END	{ printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
1097daaffb31Sdp	' /tmp/$$.diffs > /tmp/$$.file1
10987c478bd9Sstevel@tonic-gate
1099daaffb31Sdp	#
1100daaffb31Sdp	#  Now generate the HTML for the new file
1101daaffb31Sdp	#
1102cdf0c1d5Smjnelson	$AWK '
1103daaffb31Sdp	BEGIN	{
1104daaffb31Sdp		printf "function sp(n) {for (i=0;i<n;i++)printf \"\\n\"}\n"
1105daaffb31Sdp		printf "function new() "
1106daaffb31Sdp		printf "{printf \"<span class=\\\"new\\\">%%4d %%s</span>\\n\", NR, $0}\n"
1107daaffb31Sdp		printf "function changed() "
1108daaffb31Sdp		printf "{printf \"<span class=\\\"changed\\\">%%4d %%s</span>\\n\", NR, $0}\n"
1109daaffb31Sdp		printf "function bl() {printf \"%%4d %%s\\n\", NR, $0}\n"
1110daaffb31Sdp	}
11117c478bd9Sstevel@tonic-gate
1112daaffb31Sdp	/^</	{next}
1113daaffb31Sdp	/^>/	{next}
1114daaffb31Sdp	/^---/	{next}
1115daaffb31Sdp
1116daaffb31Sdp	{
11177c478bd9Sstevel@tonic-gate	split($1, a, /[cad]/) ;
11187c478bd9Sstevel@tonic-gate	if (index($1, "d")) {
11197c478bd9Sstevel@tonic-gate		if (a[2] == 0) {
11207c478bd9Sstevel@tonic-gate			n = split(a[1], r, /,/);
11217c478bd9Sstevel@tonic-gate			if (n == 1)
11227c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(1)}\n"
11237c478bd9Sstevel@tonic-gate			else
11247c478bd9Sstevel@tonic-gate				printf "BEGIN\t\t{sp(%d)}\n",\
11257c478bd9Sstevel@tonic-gate				(r[2] - r[1]) + 1
11267c478bd9Sstevel@tonic-gate			next
11277c478bd9Sstevel@tonic-gate		}
11287c478bd9Sstevel@tonic-gate
11297c478bd9Sstevel@tonic-gate		printf "NR==%s\t\t{", a[2]
11307c478bd9Sstevel@tonic-gate		n = split(a[1], r, /,/);
11317c478bd9Sstevel@tonic-gate		s = r[1];
11327c478bd9Sstevel@tonic-gate		if (n == 1)
11337c478bd9Sstevel@tonic-gate			printf "bl();printf \"\\n\"; next}\n"
11347c478bd9Sstevel@tonic-gate		else {
11357c478bd9Sstevel@tonic-gate			n = r[2] - r[1]
11367c478bd9Sstevel@tonic-gate			printf "bl();sp(%d);next}\n",\
11377c478bd9Sstevel@tonic-gate			(r[2] - r[1]) + 1
11387c478bd9Sstevel@tonic-gate		}
1139daaffb31Sdp		next
11407c478bd9Sstevel@tonic-gate	}
11417c478bd9Sstevel@tonic-gate	if (index($1, "a")) {
11427c478bd9Sstevel@tonic-gate		n = split(a[2], r, /,/);
11437c478bd9Sstevel@tonic-gate		n1 = r[1]
11447c478bd9Sstevel@tonic-gate		n2 = r[2]
11457c478bd9Sstevel@tonic-gate		if (n == 1)
1146daaffb31Sdp			printf "NR==%s\t\t{new() ; next}\n" , n1
11477c478bd9Sstevel@tonic-gate		else
1148daaffb31Sdp			printf "NR==%s,NR==%s\t{new() ; next}\n" , n1, n2
1149daaffb31Sdp		next
11507c478bd9Sstevel@tonic-gate	}
11517c478bd9Sstevel@tonic-gate	if (index($1, "c")) {
11527c478bd9Sstevel@tonic-gate		n = split(a[2], r, /,/);
11537c478bd9Sstevel@tonic-gate		n1 = r[1]
11547c478bd9Sstevel@tonic-gate		n2 = r[2]
11557c478bd9Sstevel@tonic-gate		final = n2
11567c478bd9Sstevel@tonic-gate		d2 = 0;
11577c478bd9Sstevel@tonic-gate		if (n == 1) {
11587c478bd9Sstevel@tonic-gate			final = n1
1159daaffb31Sdp			printf "NR==%s\t\t{changed();" , n1
11607c478bd9Sstevel@tonic-gate		} else {
11617c478bd9Sstevel@tonic-gate			d2 = n2 - n1
1162daaffb31Sdp			printf "NR==%s,NR==%s\t{changed();" , n1, n2
11637c478bd9Sstevel@tonic-gate		}
11647c478bd9Sstevel@tonic-gate		m = split(a[1], r, /,/);
11657c478bd9Sstevel@tonic-gate		n1 = r[1]
11667c478bd9Sstevel@tonic-gate		n2 = r[2]
11677c478bd9Sstevel@tonic-gate		if (m > 1) {
11687c478bd9Sstevel@tonic-gate			d1  = n2 - n1
11697c478bd9Sstevel@tonic-gate			if (d1 > d2) {
11707c478bd9Sstevel@tonic-gate				if (n > 1) printf "if (NR==%d)", final
11717c478bd9Sstevel@tonic-gate				printf "sp(%d);", d1 - d2
11727c478bd9Sstevel@tonic-gate			}
11737c478bd9Sstevel@tonic-gate		}
11747c478bd9Sstevel@tonic-gate		printf "next}\n" ;
1175daaffb31Sdp		next
11767c478bd9Sstevel@tonic-gate	}
1177daaffb31Sdp	}
1178daaffb31Sdp	END	{ printf "{printf \"%%4d %%s\\n\", NR, $0 }\n" }
1179daaffb31Sdp	' /tmp/$$.diffs > /tmp/$$.file2
11807c478bd9Sstevel@tonic-gate
1181daaffb31Sdp	#
1182cdf0c1d5Smjnelson	# Post-process the HTML files by running them back through $AWK
1183daaffb31Sdp	#
1184cdf0c1d5Smjnelson	html_quote < $1 | $AWK -f /tmp/$$.file1 > /tmp/$$.file1.html
11857c478bd9Sstevel@tonic-gate
1186cdf0c1d5Smjnelson	html_quote < $2 | $AWK -f /tmp/$$.file2 > /tmp/$$.file2.html
11877c478bd9Sstevel@tonic-gate
1188daaffb31Sdp	#
1189daaffb31Sdp	# Now combine into a valid HTML file and side-by-side into a table
1190daaffb31Sdp	#
1191daaffb31Sdp	print "$HTML<head>$STDHEAD"
1192cdf0c1d5Smjnelson	print "<title>$WNAME Sdiff $TPATH/$TNAME</title>"
1193daaffb31Sdp	print "</head><body id=\"SUNWwebrev\">"
1194b0efaad7SJoshua M. Clulow	print "<a class=\"print\" href=\"javascript:print()\">Print this page</a>"
1195daaffb31Sdp	print "<pre>$COMMENT</pre>\n"
1196daaffb31Sdp	print "<table><tr valign=\"top\">"
1197daaffb31Sdp	print "<td><pre>"
11987c478bd9Sstevel@tonic-gate
1199daaffb31Sdp	strip_unchanged /tmp/$$.file1.html
12007c478bd9Sstevel@tonic-gate
1201daaffb31Sdp	print "</pre></td><td><pre>"
12027c478bd9Sstevel@tonic-gate
1203daaffb31Sdp	strip_unchanged /tmp/$$.file2.html
12047c478bd9Sstevel@tonic-gate
1205daaffb31Sdp	print "</pre></td>"
1206daaffb31Sdp	print "</tr></table>"
1207daaffb31Sdp	print "</body></html>"
12087c478bd9Sstevel@tonic-gate
1209daaffb31Sdp	framed_sdiff $TNAME $TPATH /tmp/$$.file1.html /tmp/$$.file2.html \
1210daaffb31Sdp	    "$COMMENT"
12117c478bd9Sstevel@tonic-gate}
12127c478bd9Sstevel@tonic-gate
12137c478bd9Sstevel@tonic-gate
1214daaffb31Sdp#
1215daaffb31Sdp# framed_sdiff <filename> <filepath> <lhsfile> <rhsfile> <comment>
1216daaffb31Sdp#
1217daaffb31Sdp# Expects lefthand and righthand side html files created by sdiff_to_html.
1218daaffb31Sdp# We use insert_anchors() to augment those with HTML navigation anchors,
1219daaffb31Sdp# and then emit the main frame.  Content is placed into:
1220daaffb31Sdp#
1221daaffb31Sdp#    $WDIR/DIR/$TNAME.lhs.html
1222daaffb31Sdp#    $WDIR/DIR/$TNAME.rhs.html
1223daaffb31Sdp#    $WDIR/DIR/$TNAME.frames.html
1224daaffb31Sdp#
1225daaffb31Sdp# NOTE: We rely on standard usage of $WDIR and $DIR.
1226daaffb31Sdp#
12277c478bd9Sstevel@tonic-gatefunction framed_sdiff
12287c478bd9Sstevel@tonic-gate{
1229daaffb31Sdp	typeset TNAME=$1
1230daaffb31Sdp	typeset TPATH=$2
1231daaffb31Sdp	typeset lhsfile=$3
1232daaffb31Sdp	typeset rhsfile=$4
1233daaffb31Sdp	typeset comments=$5
1234daaffb31Sdp	typeset RTOP
1235daaffb31Sdp
1236daaffb31Sdp	# Enable html files to access WDIR via a relative path.
1237daaffb31Sdp	RTOP=$(relative_dir $TPATH $WDIR)
1238daaffb31Sdp
1239daaffb31Sdp	# Make the rhs/lhs files and output the frameset file.
1240daaffb31Sdp	print "$HTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.lhs.html
1241daaffb31Sdp
1242daaffb31Sdp	cat >> $WDIR/$DIR/$TNAME.lhs.html <<-EOF
12438b3b7b16SMark J. Nelson	    <script type="text/javascript" src="${RTOP}ancnav.js"></script>
1244daaffb31Sdp	    </head>
1245daaffb31Sdp	    <body id="SUNWwebrev" onkeypress="keypress(event);">
1246cac38512Smjnelson	    <a name="0"></a>
1247cac38512Smjnelson	    <pre>$comments</pre><hr></hr>
1248daaffb31Sdp	EOF
1249daaffb31Sdp
1250daaffb31Sdp	cp $WDIR/$DIR/$TNAME.lhs.html $WDIR/$DIR/$TNAME.rhs.html
1251daaffb31Sdp
1252daaffb31Sdp	insert_anchors $lhsfile >> $WDIR/$DIR/$TNAME.lhs.html
1253daaffb31Sdp	insert_anchors $rhsfile >> $WDIR/$DIR/$TNAME.rhs.html
1254daaffb31Sdp
1255daaffb31Sdp	close='</body></html>'
1256daaffb31Sdp
1257daaffb31Sdp	print $close >> $WDIR/$DIR/$TNAME.lhs.html
1258daaffb31Sdp	print $close >> $WDIR/$DIR/$TNAME.rhs.html
1259daaffb31Sdp
1260daaffb31Sdp	print "$FRAMEHTML<head>$STDHEAD" > $WDIR/$DIR/$TNAME.frames.html
1261daaffb31Sdp	print "<title>$WNAME Framed-Sdiff " \
1262daaffb31Sdp	    "$TPATH/$TNAME</title> </head>" >> $WDIR/$DIR/$TNAME.frames.html
1263daaffb31Sdp	cat >> $WDIR/$DIR/$TNAME.frames.html <<-EOF
1264daaffb31Sdp	  <frameset rows="*,60">
1265daaffb31Sdp	    <frameset cols="50%,50%">
1266cac38512Smjnelson	      <frame src="$TNAME.lhs.html" scrolling="auto" name="lhs"></frame>
1267cac38512Smjnelson	      <frame src="$TNAME.rhs.html" scrolling="auto" name="rhs"></frame>
1268daaffb31Sdp	    </frameset>
12698b3b7b16SMark J. Nelson	  <frame src="${RTOP}ancnav.html" scrolling="no" marginwidth="0"
1270cac38512Smjnelson	   marginheight="0" name="nav"></frame>
1271daaffb31Sdp	  <noframes>
1272b0efaad7SJoshua M. Clulow	    <body id="SUNWwebrev">
1273daaffb31Sdp	      Alas 'frames' webrev requires that your browser supports frames
1274daaffb31Sdp	      and has the feature enabled.
1275b0efaad7SJoshua M. Clulow	    </body>
1276daaffb31Sdp	  </noframes>
1277daaffb31Sdp	  </frameset>
12787c478bd9Sstevel@tonic-gate	</html>
12797c478bd9Sstevel@tonic-gate	EOF
12807c478bd9Sstevel@tonic-gate}
12817c478bd9Sstevel@tonic-gate
12827c478bd9Sstevel@tonic-gate
1283daaffb31Sdp#
1284daaffb31Sdp# input_cmd | insert_anchors | output_cmd
1285daaffb31Sdp#
12867c478bd9Sstevel@tonic-gate# Flag blocks of difference with sequentially numbered invisible
1287daaffb31Sdp# anchors.  These are used to drive the frames version of the
12887c478bd9Sstevel@tonic-gate# sdiffs output.
12897c478bd9Sstevel@tonic-gate#
12907c478bd9Sstevel@tonic-gate# NOTE: Anchor zero flags the top of the file irrespective of changes,
12917c478bd9Sstevel@tonic-gate# an additional anchor is also appended to flag the bottom.
12927c478bd9Sstevel@tonic-gate#
1293daaffb31Sdp# The script detects changed lines as any line that has a "<span
1294daaffb31Sdp# class=" string embedded (unchanged lines have no class set and are
1295daaffb31Sdp# not part of a <span>.  Blank lines (without a sequence number)
12967c478bd9Sstevel@tonic-gate# are also detected since they flag lines that have been inserted or
12977c478bd9Sstevel@tonic-gate# deleted.
12987c478bd9Sstevel@tonic-gate#
1299daaffb31Sdpfunction insert_anchors
1300daaffb31Sdp{
1301cdf0c1d5Smjnelson	$AWK '
1302daaffb31Sdp	function ia() {
1303daaffb31Sdp		printf "<a name=\"%d\" id=\"anc%d\"></a>", anc, anc++;
1304daaffb31Sdp	}
13057c478bd9Sstevel@tonic-gate
1306daaffb31Sdp	BEGIN {
1307daaffb31Sdp		anc=1;
13087c478bd9Sstevel@tonic-gate		inblock=1;
1309daaffb31Sdp		printf "<pre>\n";
13107c478bd9Sstevel@tonic-gate	}
1311daaffb31Sdp	NF == 0 || /^<span class=/ {
1312daaffb31Sdp		if (inblock == 0) {
1313daaffb31Sdp			ia();
1314daaffb31Sdp			inblock=1;
1315daaffb31Sdp		}
1316daaffb31Sdp		print;
1317daaffb31Sdp		next;
1318daaffb31Sdp	}
1319daaffb31Sdp	{
1320daaffb31Sdp		inblock=0;
1321daaffb31Sdp		print;
1322daaffb31Sdp	}
1323daaffb31Sdp	END {
1324daaffb31Sdp		ia();
13257c478bd9Sstevel@tonic-gate
1326daaffb31Sdp		printf "<b style=\"font-size: large; color: red\">";
1327daaffb31Sdp		printf "--- EOF ---</b>"
1328e6ccc173SEdward Pilatowicz		for(i=0;i<8;i++) printf "\n\n\n\n\n\n\n\n\n\n";
1329daaffb31Sdp		printf "</pre>"
1330daaffb31Sdp		printf "<form name=\"eof\">";
1331cac38512Smjnelson		printf "<input name=\"value\" value=\"%d\" " \
1332cac38512Smjnelson		    "type=\"hidden\"></input>", anc - 1;
1333daaffb31Sdp		printf "</form>";
1334daaffb31Sdp	}
1335daaffb31Sdp	' $1
13367c478bd9Sstevel@tonic-gate}
13377c478bd9Sstevel@tonic-gate
13387c478bd9Sstevel@tonic-gate
13397c478bd9Sstevel@tonic-gate#
1340daaffb31Sdp# relative_dir
13417c478bd9Sstevel@tonic-gate#
1342daaffb31Sdp# Print a relative return path from $1 to $2.  For example if
1343daaffb31Sdp# $1=/tmp/myreview/raw_files/usr/src/tools/scripts and $2=/tmp/myreview,
1344daaffb31Sdp# this function would print "../../../../".
13457c478bd9Sstevel@tonic-gate#
1346daaffb31Sdp# In the event that $1 is not in $2 a warning is printed to stderr,
1347daaffb31Sdp# and $2 is returned-- the result of this is that the resulting webrev
1348daaffb31Sdp# is not relocatable.
1349daaffb31Sdp#
1350daaffb31Sdpfunction relative_dir
1351daaffb31Sdp{
1352b0efaad7SJoshua M. Clulow	typeset cur="${1##$2?(/)}"
1353b0efaad7SJoshua M. Clulow
1354b0efaad7SJoshua M. Clulow	#
1355b0efaad7SJoshua M. Clulow	# If the first path was specified absolutely, and it does
1356b0efaad7SJoshua M. Clulow	# not start with the second path, it's an error.
1357b0efaad7SJoshua M. Clulow	#
1358b1374179SBill Sommerfeld	if [[ "$cur" == "/${1#/}" ]]; then
1359b0efaad7SJoshua M. Clulow		# Should never happen.
1360b0efaad7SJoshua M. Clulow		print -u2 "\nWARNING: relative_dir: \"$1\" not relative "
1361b0efaad7SJoshua M. Clulow		print -u2 "to \"$2\".  Check input paths.  Framed webrev "
1362b0efaad7SJoshua M. Clulow		print -u2 "will not be relocatable!"
1363b0efaad7SJoshua M. Clulow		print $2
1364b0efaad7SJoshua M. Clulow		return
1365b0efaad7SJoshua M. Clulow	fi
1366daaffb31Sdp
13678b3b7b16SMark J. Nelson	#
13688b3b7b16SMark J. Nelson	# This is kind of ugly.  The sed script will do the following:
13698b3b7b16SMark J. Nelson	#
13708b3b7b16SMark J. Nelson	# 1. Strip off a leading "." or "./": this is important to get
13718b3b7b16SMark J. Nelson	#    the correct arcnav links for files in $WDIR.
1372e6ccc173SEdward Pilatowicz	# 2. Strip off a trailing "/": this is not strictly necessary,
13738b3b7b16SMark J. Nelson	#    but is kind of nice, since it doesn't end up in "//" at
13748b3b7b16SMark J. Nelson	#    the end of a relative path.
13758b3b7b16SMark J. Nelson	# 3. Replace all remaining sequences of non-"/" with "..": the
13768b3b7b16SMark J. Nelson	#    assumption here is that each dirname represents another
13778b3b7b16SMark J. Nelson	#    level of relative separation.
13788b3b7b16SMark J. Nelson	# 4. Append a trailing "/" only for non-empty paths: this way
13798b3b7b16SMark J. Nelson	#    the caller doesn't need to duplicate this logic, and does
13808b3b7b16SMark J. Nelson	#    not end up using $RTOP/file for files in $WDIR.
13818b3b7b16SMark J. Nelson	#
13820fd2682eSMark J. Nelson	print $cur | $SED -e '{
13830fd2682eSMark J. Nelson		s:^\./*::
13840fd2682eSMark J. Nelson		s:/$::
13850fd2682eSMark J. Nelson		s:[^/][^/]*:..:g
13860fd2682eSMark J. Nelson		s:^\(..*\)$:\1/:
13870fd2682eSMark J. Nelson	}'
13887c478bd9Sstevel@tonic-gate}
13897c478bd9Sstevel@tonic-gate
1390daaffb31Sdp#
1391daaffb31Sdp# frame_nav_js
1392daaffb31Sdp#
1393daaffb31Sdp# Emit javascript for frame navigation
1394daaffb31Sdp#
1395daaffb31Sdpfunction frame_nav_js
13967c478bd9Sstevel@tonic-gate{
13977c478bd9Sstevel@tonic-gatecat << \EOF
13987c478bd9Sstevel@tonic-gatevar myInt;
1399b0efaad7SJoshua M. Clulowvar scrolling = 0;
1400daaffb31Sdpvar sfactor = 3;
1401b0efaad7SJoshua M. Clulowvar scount = 10;
14027c478bd9Sstevel@tonic-gate
1403b0efaad7SJoshua M. Clulowfunction scrollByPix()
1404b0efaad7SJoshua M. Clulow{
1405b0efaad7SJoshua M. Clulow	if (scount <= 0) {
1406b0efaad7SJoshua M. Clulow		sfactor *= 1.2;
1407b0efaad7SJoshua M. Clulow		scount = 10;
14087c478bd9Sstevel@tonic-gate	}
1409b0efaad7SJoshua M. Clulow	parent.lhs.scrollBy(0, sfactor);
1410b0efaad7SJoshua M. Clulow	parent.rhs.scrollBy(0, sfactor);
14117c478bd9Sstevel@tonic-gate	scount--;
14127c478bd9Sstevel@tonic-gate}
14137c478bd9Sstevel@tonic-gate
1414b0efaad7SJoshua M. Clulowfunction scrollToAnc(num)
1415b0efaad7SJoshua M. Clulow{
1416daaffb31Sdp	// Update the value of the anchor in the form which we use as
1417daaffb31Sdp	// storage for this value.  setAncValue() will take care of
1418daaffb31Sdp	// correcting for overflow and underflow of the value and return
1419daaffb31Sdp	// us the new value.
1420daaffb31Sdp	num = setAncValue(num);
1421daaffb31Sdp
1422daaffb31Sdp	// Set location and scroll back a little to expose previous
1423daaffb31Sdp	// lines.
1424daaffb31Sdp	//
1425daaffb31Sdp	// Note that this could be improved: it is possible although
1426daaffb31Sdp	// complex to compute the x and y position of an anchor, and to
1427daaffb31Sdp	// scroll to that location directly.
1428daaffb31Sdp	//
14297c478bd9Sstevel@tonic-gate	parent.lhs.location.replace(parent.lhs.location.pathname + "#" + num);
14307c478bd9Sstevel@tonic-gate	parent.rhs.location.replace(parent.rhs.location.pathname + "#" + num);
1431daaffb31Sdp
1432b0efaad7SJoshua M. Clulow	parent.lhs.scrollBy(0, -30);
1433b0efaad7SJoshua M. Clulow	parent.rhs.scrollBy(0, -30);
14347c478bd9Sstevel@tonic-gate}
14357c478bd9Sstevel@tonic-gate
1436daaffb31Sdpfunction getAncValue()
1437daaffb31Sdp{
1438daaffb31Sdp	return (parseInt(parent.nav.document.diff.real.value));
1439daaffb31Sdp}
1440daaffb31Sdp
1441daaffb31Sdpfunction setAncValue(val)
1442daaffb31Sdp{
1443daaffb31Sdp	if (val <= 0) {
1444daaffb31Sdp		val = 0;
1445daaffb31Sdp		parent.nav.document.diff.real.value = val;
1446daaffb31Sdp		parent.nav.document.diff.display.value = "BOF";
1447daaffb31Sdp		return (val);
1448daaffb31Sdp	}
1449daaffb31Sdp
1450daaffb31Sdp	//
1451daaffb31Sdp	// The way we compute the max anchor value is to stash it
1452daaffb31Sdp	// inline in the left and right hand side pages-- it's the same
1453daaffb31Sdp	// on each side, so we pluck from the left.
1454daaffb31Sdp	//
1455daaffb31Sdp	maxval = parent.lhs.document.eof.value.value;
1456daaffb31Sdp	if (val < maxval) {
1457daaffb31Sdp		parent.nav.document.diff.real.value = val;
1458daaffb31Sdp		parent.nav.document.diff.display.value = val.toString();
1459daaffb31Sdp		return (val);
1460daaffb31Sdp	}
1461daaffb31Sdp
1462daaffb31Sdp	// this must be: val >= maxval
1463daaffb31Sdp	val = maxval;
1464daaffb31Sdp	parent.nav.document.diff.real.value = val;
1465daaffb31Sdp	parent.nav.document.diff.display.value = "EOF";
1466daaffb31Sdp	return (val);
1467daaffb31Sdp}
1468daaffb31Sdp
1469b0efaad7SJoshua M. Clulowfunction stopScroll()
1470b0efaad7SJoshua M. Clulow{
1471b0efaad7SJoshua M. Clulow	if (scrolling == 1) {
14727c478bd9Sstevel@tonic-gate		clearInterval(myInt);
1473b0efaad7SJoshua M. Clulow		scrolling = 0;
14747c478bd9Sstevel@tonic-gate	}
14757c478bd9Sstevel@tonic-gate}
14767c478bd9Sstevel@tonic-gate
1477b0efaad7SJoshua M. Clulowfunction startScroll()
1478b0efaad7SJoshua M. Clulow{
14797c478bd9Sstevel@tonic-gate	stopScroll();
1480b0efaad7SJoshua M. Clulow	scrolling = 1;
1481b0efaad7SJoshua M. Clulow	myInt = setInterval("scrollByPix()", 10);
14827c478bd9Sstevel@tonic-gate}
14837c478bd9Sstevel@tonic-gate
1484b0efaad7SJoshua M. Clulowfunction handlePress(b)
1485b0efaad7SJoshua M. Clulow{
14867c478bd9Sstevel@tonic-gate	switch (b) {
1487b0efaad7SJoshua M. Clulow	case 1:
1488daaffb31Sdp		scrollToAnc(-1);
14897c478bd9Sstevel@tonic-gate		break;
1490b0efaad7SJoshua M. Clulow	case 2:
1491daaffb31Sdp		scrollToAnc(getAncValue() - 1);
14927c478bd9Sstevel@tonic-gate		break;
1493b0efaad7SJoshua M. Clulow	case 3:
1494b0efaad7SJoshua M. Clulow		sfactor = -3;
14957c478bd9Sstevel@tonic-gate		startScroll();
14967c478bd9Sstevel@tonic-gate		break;
1497b0efaad7SJoshua M. Clulow	case 4:
1498b0efaad7SJoshua M. Clulow		sfactor = 3;
14997c478bd9Sstevel@tonic-gate		startScroll();
15007c478bd9Sstevel@tonic-gate		break;
1501b0efaad7SJoshua M. Clulow	case 5:
1502daaffb31Sdp		scrollToAnc(getAncValue() + 1);
15037c478bd9Sstevel@tonic-gate		break;
1504b0efaad7SJoshua M. Clulow	case 6:
1505daaffb31Sdp		scrollToAnc(999999);
15067c478bd9Sstevel@tonic-gate		break;
15077c478bd9Sstevel@tonic-gate	}
15087c478bd9Sstevel@tonic-gate}
15097c478bd9Sstevel@tonic-gate
1510b0efaad7SJoshua M. Clulowfunction handleRelease(b)
1511b0efaad7SJoshua M. Clulow{
15127c478bd9Sstevel@tonic-gate	stopScroll();
15137c478bd9Sstevel@tonic-gate}
15147c478bd9Sstevel@tonic-gate
1515b0efaad7SJoshua M. Clulowfunction keypress(ev)
1516b0efaad7SJoshua M. Clulow{
1517daaffb31Sdp	var keynum;
1518daaffb31Sdp	var keychar;
1519daaffb31Sdp
1520daaffb31Sdp	if (window.event) { // IE
1521daaffb31Sdp		keynum = ev.keyCode;
1522daaffb31Sdp	} else if (ev.which) { // non-IE
1523daaffb31Sdp		keynum = ev.which;
1524daaffb31Sdp	}
1525daaffb31Sdp
1526daaffb31Sdp	keychar = String.fromCharCode(keynum);
1527daaffb31Sdp
1528daaffb31Sdp	if (keychar == "k") {
1529daaffb31Sdp		handlePress(2);
1530daaffb31Sdp		return (0);
1531daaffb31Sdp	} else if (keychar == "j" || keychar == " ") {
1532daaffb31Sdp		handlePress(5);
1533daaffb31Sdp		return (0);
1534daaffb31Sdp	}
1535b0efaad7SJoshua M. Clulow
1536daaffb31Sdp	return (1);
1537daaffb31Sdp}
1538daaffb31Sdp
1539b0efaad7SJoshua M. Clulowfunction ValidateDiffNum()
1540b0efaad7SJoshua M. Clulow{
1541b0efaad7SJoshua M. Clulow	var val;
1542b0efaad7SJoshua M. Clulow	var i;
1543b0efaad7SJoshua M. Clulow
1544daaffb31Sdp	val = parent.nav.document.diff.display.value;
1545daaffb31Sdp	if (val == "EOF") {
1546daaffb31Sdp		scrollToAnc(999999);
1547daaffb31Sdp		return;
15487c478bd9Sstevel@tonic-gate	}
1549daaffb31Sdp
1550daaffb31Sdp	if (val == "BOF") {
1551daaffb31Sdp		scrollToAnc(0);
1552daaffb31Sdp		return;
1553daaffb31Sdp	}
1554daaffb31Sdp
1555b0efaad7SJoshua M. Clulow	i = parseInt(val);
1556b0efaad7SJoshua M. Clulow	if (isNaN(i)) {
1557b0efaad7SJoshua M. Clulow		parent.nav.document.diff.display.value = getAncValue();
1558b0efaad7SJoshua M. Clulow	} else {
1559b0efaad7SJoshua M. Clulow		scrollToAnc(i);
1560b0efaad7SJoshua M. Clulow	}
15617c478bd9Sstevel@tonic-gate
1562b0efaad7SJoshua M. Clulow	return (false);
1563b0efaad7SJoshua M. Clulow}
1564daaffb31SdpEOF
1565daaffb31Sdp}
1566daaffb31Sdp
1567daaffb31Sdp#
1568daaffb31Sdp# frame_navigation
1569daaffb31Sdp#
1570daaffb31Sdp# Output anchor navigation file for framed sdiffs.
1571daaffb31Sdp#
1572daaffb31Sdpfunction frame_navigation
1573daaffb31Sdp{
1574daaffb31Sdp	print "$HTML<head>$STDHEAD"
1575daaffb31Sdp
1576daaffb31Sdp	cat << \EOF
1577daaffb31Sdp<title>Anchor Navigation</title>
1578daaffb31Sdp<meta http-equiv="Content-Script-Type" content="text/javascript">
1579daaffb31Sdp<meta http-equiv="Content-Type" content="text/html">
1580daaffb31Sdp
1581daaffb31Sdp<style type="text/css">
1582daaffb31Sdp    div.button td { padding-left: 5px; padding-right: 5px;
1583daaffb31Sdp		    background-color: #eee; text-align: center;
1584daaffb31Sdp		    border: 1px #444 outset; cursor: pointer; }
1585daaffb31Sdp    div.button a { font-weight: bold; color: black }
1586daaffb31Sdp    div.button td:hover { background: #ffcc99; }
1587daaffb31Sdp</style>
1588daaffb31SdpEOF
1589daaffb31Sdp
1590cac38512Smjnelson	print "<script type=\"text/javascript\" src=\"ancnav.js\"></script>"
1591daaffb31Sdp
1592daaffb31Sdp	cat << \EOF
1593daaffb31Sdp</head>
1594daaffb31Sdp<body id="SUNWwebrev" bgcolor="#eeeeee" onload="document.diff.real.focus();"
1595daaffb31Sdp	onkeypress="keypress(event);">
15967c478bd9Sstevel@tonic-gate    <noscript lang="javascript">
15977c478bd9Sstevel@tonic-gate      <center>
1598cac38512Smjnelson	<p><big>Framed Navigation controls require Javascript</big><br></br>
15997c478bd9Sstevel@tonic-gate	Either this browser is incompatable or javascript is not enabled</p>
16007c478bd9Sstevel@tonic-gate      </center>
16017c478bd9Sstevel@tonic-gate    </noscript>
16027c478bd9Sstevel@tonic-gate    <table width="100%" border="0" align="center">
1603daaffb31Sdp	<tr>
1604daaffb31Sdp          <td valign="middle" width="25%">Diff navigation:
1605daaffb31Sdp          Use 'j' and 'k' for next and previous diffs; or use buttons
1606daaffb31Sdp          at right</td>
1607daaffb31Sdp	  <td align="center" valign="top" width="50%">
16087c478bd9Sstevel@tonic-gate	    <div class="button">
1609daaffb31Sdp	      <table border="0" align="center">
1610daaffb31Sdp                  <tr>
1611daaffb31Sdp		    <td>
16127c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(1);return true;"
16137c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(1);return true;"
16147c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(1);return true;"
16157c478bd9Sstevel@tonic-gate			 onClick="return false;"
16167c478bd9Sstevel@tonic-gate			 title="Go to Beginning Of file">BOF</a></td>
1617daaffb31Sdp		    <td>
16187c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(3);return true;"
16197c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(3);return true;"
16207c478bd9Sstevel@tonic-gate			 onMouseOut="handleRelease(3);return true;"
16217c478bd9Sstevel@tonic-gate			 title="Scroll Up: Press and Hold to accelerate"
1622daaffb31Sdp			 onClick="return false;">Scroll Up</a></td>
1623daaffb31Sdp		    <td>
16247c478bd9Sstevel@tonic-gate		      <a onMouseDown="handlePress(2);return true;"
16257c478bd9Sstevel@tonic-gate			 onMouseUp="handleRelease(2);return true;"
1626daaffb31Sdp			 onMouseOut="handleRelease(2);return true;"
16277c478bd9Sstevel@tonic-gate			 title="Go to previous Diff"
16287c478bd9Sstevel@tonic-gate			 onClick="return false;">Prev Diff</a>
16297c478bd9Sstevel@tonic-gate		    </td></tr>
1630daaffb31Sdp
16317c478bd9Sstevel@tonic-gate		  <tr>
1632daaffb31Sdp		    <td>
1633daaffb31Sdp		      <a onMouseDown="handlePress(6);return true;"
1634daaffb31Sdp			 onMouseUp="handleRelease(6);return true;"
1635daaffb31Sdp			 onMouseOut="handleRelease(6);return true;"
16367c478bd9Sstevel@tonic-gate			 onClick="return false;"
16377c478bd9Sstevel@tonic-gate			 title="Go to End Of File">EOF</a></td>
1638daaffb31Sdp		    <td>
1639daaffb31Sdp		      <a onMouseDown="handlePress(4);return true;"
1640daaffb31Sdp			 onMouseUp="handleRelease(4);return true;"
1641daaffb31Sdp			 onMouseOut="handleRelease(4);return true;"
16427c478bd9Sstevel@tonic-gate			 title="Scroll Down: Press and Hold to accelerate"
1643daaffb31Sdp			 onClick="return false;">Scroll Down</a></td>
1644daaffb31Sdp		    <td>
1645daaffb31Sdp		      <a onMouseDown="handlePress(5);return true;"
1646daaffb31Sdp			 onMouseUp="handleRelease(5);return true;"
1647daaffb31Sdp			 onMouseOut="handleRelease(5);return true;"
16487c478bd9Sstevel@tonic-gate			 title="Go to next Diff"
16497c478bd9Sstevel@tonic-gate			 onClick="return false;">Next Diff</a></td>
1650daaffb31Sdp		  </tr>
1651daaffb31Sdp              </table>
1652daaffb31Sdp	    </div>
1653daaffb31Sdp	  </td>
16547c478bd9Sstevel@tonic-gate	  <th valign="middle" width="25%">
1655daaffb31Sdp	    <form action="" name="diff" onsubmit="return ValidateDiffNum();">
1656cac38512Smjnelson		<input name="display" value="BOF" size="8" type="text"></input>
1657cac38512Smjnelson		<input name="real" value="0" size="8" type="hidden"></input>
16587c478bd9Sstevel@tonic-gate	    </form>
16597c478bd9Sstevel@tonic-gate	  </th>
1660daaffb31Sdp	</tr>
16617c478bd9Sstevel@tonic-gate    </table>
16627c478bd9Sstevel@tonic-gate  </body>
16637c478bd9Sstevel@tonic-gate</html>
16647c478bd9Sstevel@tonic-gateEOF
16657c478bd9Sstevel@tonic-gate}
16667c478bd9Sstevel@tonic-gate
16677c478bd9Sstevel@tonic-gate
1668daaffb31Sdp
1669daaffb31Sdp#
1670daaffb31Sdp# diff_to_html <filename> <filepath> { U | C } <comment>
1671daaffb31Sdp#
1672daaffb31Sdp# Processes the output of diff to produce an HTML file representing either
1673daaffb31Sdp# context or unified diffs.
1674daaffb31Sdp#
1675daaffb31Sdpdiff_to_html()
1676daaffb31Sdp{
1677daaffb31Sdp	TNAME=$1
1678daaffb31Sdp	TPATH=$2
1679daaffb31Sdp	DIFFTYPE=$3
1680daaffb31Sdp	COMMENT=$4
1681daaffb31Sdp
1682daaffb31Sdp	print "$HTML<head>$STDHEAD"
1683daaffb31Sdp	print "<title>$WNAME ${DIFFTYPE}diff $TPATH</title>"
1684daaffb31Sdp
1685daaffb31Sdp	if [[ $DIFFTYPE == "U" ]]; then
1686daaffb31Sdp		print "$UDIFFCSS"
1687daaffb31Sdp	fi
1688daaffb31Sdp
1689daaffb31Sdp	cat <<-EOF
1690daaffb31Sdp	</head>
1691daaffb31Sdp	<body id="SUNWwebrev">
1692daaffb31Sdp        <a class="print" href="javascript:print()">Print this page</a>
1693daaffb31Sdp	<pre>$COMMENT</pre>
1694daaffb31Sdp        <pre>
1695daaffb31Sdp	EOF
1696daaffb31Sdp
1697cdf0c1d5Smjnelson	html_quote | $AWK '
1698daaffb31Sdp	/^--- new/	{ next }
1699daaffb31Sdp	/^\+\+\+ new/	{ next }
1700daaffb31Sdp	/^--- old/	{ next }
1701daaffb31Sdp	/^\*\*\* old/	{ next }
1702daaffb31Sdp	/^\*\*\*\*/	{ next }
1703daaffb31Sdp	/^-------/	{ printf "<center><h1>%s</h1></center>\n", $0; next }
1704cac38512Smjnelson	/^\@\@.*\@\@$/	{ printf "</pre><hr></hr><pre>\n";
1705daaffb31Sdp			  printf "<span class=\"newmarker\">%s</span>\n", $0;
1706daaffb31Sdp			  next}
1707daaffb31Sdp
1708cac38512Smjnelson	/^\*\*\*/	{ printf "<hr></hr><span class=\"oldmarker\">%s</span>\n", $0;
1709daaffb31Sdp			  next}
1710daaffb31Sdp	/^---/		{ printf "<span class=\"newmarker\">%s</span>\n", $0;
1711daaffb31Sdp			  next}
1712daaffb31Sdp	/^\+/		{printf "<span class=\"new\">%s</span>\n", $0; next}
1713daaffb31Sdp	/^!/		{printf "<span class=\"changed\">%s</span>\n", $0; next}
1714daaffb31Sdp	/^-/		{printf "<span class=\"removed\">%s</span>\n", $0; next}
1715daaffb31Sdp			{printf "%s\n", $0; next}
1716daaffb31Sdp	'
1717daaffb31Sdp
1718daaffb31Sdp	print "</pre></body></html>\n"
17197c478bd9Sstevel@tonic-gate}
17207c478bd9Sstevel@tonic-gate
17217c478bd9Sstevel@tonic-gate
1722daaffb31Sdp#
1723daaffb31Sdp# source_to_html { new | old } <filename>
1724daaffb31Sdp#
1725daaffb31Sdp# Process a plain vanilla source file to transform it into an HTML file.
1726daaffb31Sdp#
17277c478bd9Sstevel@tonic-gatesource_to_html()
17287c478bd9Sstevel@tonic-gate{
1729daaffb31Sdp	WHICH=$1
1730daaffb31Sdp	TNAME=$2
1731daaffb31Sdp
1732daaffb31Sdp	print "$HTML<head>$STDHEAD"
1733cdf0c1d5Smjnelson	print "<title>$WNAME $WHICH $TNAME</title>"
1734daaffb31Sdp	print "<body id=\"SUNWwebrev\">"
1735daaffb31Sdp	print "<pre>"
1736cdf0c1d5Smjnelson	html_quote | $AWK '{line += 1 ; printf "%4d %s\n", line, $0 }'
1737daaffb31Sdp	print "</pre></body></html>"
17387c478bd9Sstevel@tonic-gate}
17397c478bd9Sstevel@tonic-gate
1740daaffb31Sdp#
1741cdf0c1d5Smjnelson# comments_from_wx {text|html} filepath
1742cdf0c1d5Smjnelson#
1743cdf0c1d5Smjnelson# Given the pathname of a file, find its location in a "wx" active
1744cdf0c1d5Smjnelson# file list and print the following comment.  Output is either text or
1745cdf0c1d5Smjnelson# HTML; if the latter, embedded bugids (sequence of 5 or more digits)
1746cdf0c1d5Smjnelson# are turned into URLs.
1747daaffb31Sdp#
1748daaffb31Sdpcomments_from_wx()
17497c478bd9Sstevel@tonic-gate{
1750daaffb31Sdp	typeset fmt=$1
1751daaffb31Sdp	typeset p=$2
17527c478bd9Sstevel@tonic-gate
1753b1374179SBill Sommerfeld	comm=$($AWK '$1 == "'$p'" {
17547c478bd9Sstevel@tonic-gate		do getline ; while (NF > 0)
17557c478bd9Sstevel@tonic-gate		getline
17567c478bd9Sstevel@tonic-gate		while (NF > 0) { print ; getline }
17577c478bd9Sstevel@tonic-gate		exit
1758b1374179SBill Sommerfeld	}' < $wxfile)
1759daaffb31Sdp
1760cdf0c1d5Smjnelson	if [[ -z $comm ]]; then
1761cdf0c1d5Smjnelson		comm="*** NO COMMENTS ***"
1762cdf0c1d5Smjnelson	fi
1763cdf0c1d5Smjnelson
1764daaffb31Sdp	if [[ $fmt == "text" ]]; then
1765cdf0c1d5Smjnelson		print -- "$comm"
1766daaffb31Sdp		return
1767daaffb31Sdp	fi
1768daaffb31Sdp
17690fd2682eSMark J. Nelson	print -- "$comm" | html_quote | its2url
1770cdf0c1d5Smjnelson
1771daaffb31Sdp}
1772daaffb31Sdp
1773daaffb31Sdp#
1774daaffb31Sdp# getcomments {text|html} filepath parentpath
1775daaffb31Sdp#
1776daaffb31Sdp# Fetch the comments depending on what SCM mode we're in.
1777daaffb31Sdp#
1778daaffb31Sdpgetcomments()
1779daaffb31Sdp{
1780daaffb31Sdp	typeset fmt=$1
1781daaffb31Sdp	typeset p=$2
1782daaffb31Sdp	typeset pp=$3
1783daaffb31Sdp
17843df69ef3SDarren Moffat	if [[ -n $Nflag ]]; then
17853df69ef3SDarren Moffat		return
17863df69ef3SDarren Moffat	fi
17870f554fe5SRichard Lowe
1788daaffb31Sdp	if [[ -n $wxfile ]]; then
1789daaffb31Sdp		comments_from_wx $fmt $p
1790daaffb31Sdp	fi
1791daaffb31Sdp}
1792daaffb31Sdp
1793daaffb31Sdp#
1794daaffb31Sdp# printCI <total-changed> <inserted> <deleted> <modified> <unchanged>
1795daaffb31Sdp#
1796daaffb31Sdp# Print out Code Inspection figures similar to sccs-prt(1) format.
1797daaffb31Sdp#
1798daaffb31Sdpfunction printCI
1799daaffb31Sdp{
1800daaffb31Sdp	integer tot=$1 ins=$2 del=$3 mod=$4 unc=$5
1801daaffb31Sdp	typeset str
1802daaffb31Sdp	if (( tot == 1 )); then
1803daaffb31Sdp		str="line"
1804daaffb31Sdp	else
1805daaffb31Sdp		str="lines"
1806daaffb31Sdp	fi
1807daaffb31Sdp	printf '%d %s changed: %d ins; %d del; %d mod; %d unchg\n' \
1808daaffb31Sdp	    $tot $str $ins $del $mod $unc
18097c478bd9Sstevel@tonic-gate}
18107c478bd9Sstevel@tonic-gate
18117c478bd9Sstevel@tonic-gate
1812daaffb31Sdp#
1813daaffb31Sdp# difflines <oldfile> <newfile>
1814daaffb31Sdp#
1815daaffb31Sdp# Calculate and emit number of added, removed, modified and unchanged lines,
1816daaffb31Sdp# and total lines changed, the sum of added + removed + modified.
1817daaffb31Sdp#
18187c478bd9Sstevel@tonic-gatefunction difflines
18197c478bd9Sstevel@tonic-gate{
1820daaffb31Sdp	integer tot mod del ins unc err
1821daaffb31Sdp	typeset filename
1822daaffb31Sdp
1823cdf0c1d5Smjnelson	eval $( diff -e $1 $2 | $AWK '
1824daaffb31Sdp	# Change range of lines: N,Nc
1825daaffb31Sdp	/^[0-9]*,[0-9]*c$/ {
1826daaffb31Sdp		n=split(substr($1,1,length($1)-1), counts, ",");
1827daaffb31Sdp		if (n != 2) {
1828b0efaad7SJoshua M. Clulow			error=2
1829b0efaad7SJoshua M. Clulow			exit;
1830daaffb31Sdp		}
1831daaffb31Sdp		#
1832daaffb31Sdp		# 3,5c means lines 3 , 4 and 5 are changed, a total of 3 lines.
1833daaffb31Sdp		# following would be 5 - 3 = 2! Hence +1 for correction.
1834daaffb31Sdp		#
1835daaffb31Sdp		r=(counts[2]-counts[1])+1;
1836daaffb31Sdp
1837daaffb31Sdp		#
1838daaffb31Sdp		# Now count replacement lines: each represents a change instead
1839daaffb31Sdp		# of a delete, so increment c and decrement r.
1840daaffb31Sdp		#
1841daaffb31Sdp		while (getline != /^\.$/) {
1842daaffb31Sdp			c++;
1843daaffb31Sdp			r--;
1844daaffb31Sdp		}
1845daaffb31Sdp		#
1846daaffb31Sdp		# If there were more replacement lines than original lines,
1847daaffb31Sdp		# then r will be negative; in this case there are no deletions,
1848daaffb31Sdp		# but there are r changes that should be counted as adds, and
1849daaffb31Sdp		# since r is negative, subtract it from a and add it to c.
1850daaffb31Sdp		#
1851daaffb31Sdp		if (r < 0) {
1852daaffb31Sdp			a-=r;
1853daaffb31Sdp			c+=r;
1854daaffb31Sdp		}
1855daaffb31Sdp
1856daaffb31Sdp		#
1857daaffb31Sdp		# If there were more original lines than replacement lines, then
1858daaffb31Sdp		# r will be positive; in this case, increment d by that much.
1859daaffb31Sdp		#
1860daaffb31Sdp		if (r > 0) {
1861daaffb31Sdp			d+=r;
1862daaffb31Sdp		}
1863daaffb31Sdp		next;
18647c478bd9Sstevel@tonic-gate	}
1865daaffb31Sdp
1866daaffb31Sdp	# Change lines: Nc
1867daaffb31Sdp	/^[0-9].*c$/ {
1868daaffb31Sdp		# The first line is a replacement; any more are additions.
1869daaffb31Sdp		if (getline != /^\.$/) {
1870daaffb31Sdp			c++;
1871daaffb31Sdp			while (getline != /^\.$/) a++;
1872daaffb31Sdp		}
1873daaffb31Sdp		next;
18747c478bd9Sstevel@tonic-gate	}
1875daaffb31Sdp
1876daaffb31Sdp	# Add lines: both Na and N,Na
1877daaffb31Sdp	/^[0-9].*a$/ {
1878daaffb31Sdp		while (getline != /^\.$/) a++;
1879daaffb31Sdp		next;
18807c478bd9Sstevel@tonic-gate	}
1881daaffb31Sdp
1882daaffb31Sdp	# Delete range of lines: N,Nd
1883daaffb31Sdp	/^[0-9]*,[0-9]*d$/ {
1884daaffb31Sdp		n=split(substr($1,1,length($1)-1), counts, ",");
1885daaffb31Sdp		if (n != 2) {
1886daaffb31Sdp			error=2
1887daaffb31Sdp			exit;
1888daaffb31Sdp		}
1889daaffb31Sdp		#
1890daaffb31Sdp		# 3,5d means lines 3 , 4 and 5 are deleted, a total of 3 lines.
1891daaffb31Sdp		# following would be 5 - 3 = 2! Hence +1 for correction.
1892daaffb31Sdp		#
1893daaffb31Sdp		r=(counts[2]-counts[1])+1;
18947c478bd9Sstevel@tonic-gate		d+=r;
1895daaffb31Sdp		next;
18967c478bd9Sstevel@tonic-gate	}
18977c478bd9Sstevel@tonic-gate
1898daaffb31Sdp	# Delete line: Nd.   For example 10d says line 10 is deleted.
1899daaffb31Sdp	/^[0-9]*d$/ {d++; next}
1900daaffb31Sdp
1901daaffb31Sdp	# Should not get here!
1902daaffb31Sdp	{
1903daaffb31Sdp		error=1;
1904daaffb31Sdp		exit;
19057c478bd9Sstevel@tonic-gate	}
1906daaffb31Sdp
1907daaffb31Sdp	# Finish off - print results
1908daaffb31Sdp	END {
1909daaffb31Sdp		printf("tot=%d;mod=%d;del=%d;ins=%d;err=%d\n",
1910daaffb31Sdp		    (c+d+a), c, d, a, error);
1911daaffb31Sdp	}' )
1912daaffb31Sdp
1913cdf0c1d5Smjnelson	# End of $AWK, Check to see if any trouble occurred.
1914daaffb31Sdp	if (( $? > 0 || err > 0 )); then
1915daaffb31Sdp		print "Unexpected Error occurred reading" \
1916daaffb31Sdp		    "\`diff -e $1 $2\`: \$?=$?, err=" $err
1917daaffb31Sdp		return
1918daaffb31Sdp	fi
1919daaffb31Sdp
19207c478bd9Sstevel@tonic-gate	# Accumulate totals
19217c478bd9Sstevel@tonic-gate	(( TOTL += tot ))
1922daaffb31Sdp	(( TMOD += mod ))
1923daaffb31Sdp	(( TDEL += del ))
19247c478bd9Sstevel@tonic-gate	(( TINS += ins ))
19257c478bd9Sstevel@tonic-gate	# Calculate unchanged lines
1926b1374179SBill Sommerfeld	unc=$(wc -l < $1)
19277c478bd9Sstevel@tonic-gate	if (( unc > 0 )); then
1928daaffb31Sdp		(( unc -= del + mod ))
1929daaffb31Sdp		(( TUNC += unc ))
19307c478bd9Sstevel@tonic-gate	fi
19317c478bd9Sstevel@tonic-gate	# print summary
1932daaffb31Sdp	print "<span class=\"lineschanged\">"
1933daaffb31Sdp	printCI $tot $ins $del $mod $unc
1934daaffb31Sdp	print "</span>"
19357c478bd9Sstevel@tonic-gate}
19367c478bd9Sstevel@tonic-gate
1937daaffb31Sdp
19387c478bd9Sstevel@tonic-gate#
1939daaffb31Sdp# flist_from_wx
1940daaffb31Sdp#
1941daaffb31Sdp# Sets up webrev to source its information from a wx-formatted file.
1942daaffb31Sdp# Sets the global 'wxfile' variable.
1943daaffb31Sdp#
1944daaffb31Sdpfunction flist_from_wx
19457c478bd9Sstevel@tonic-gate{
1946daaffb31Sdp	typeset argfile=$1
1947daaffb31Sdp	if [[ -n ${argfile%%/*} ]]; then
1948daaffb31Sdp		#
1949daaffb31Sdp		# If the wx file pathname is relative then make it absolute
1950daaffb31Sdp		# because the webrev does a "cd" later on.
1951daaffb31Sdp		#
1952daaffb31Sdp		wxfile=$PWD/$argfile
1953daaffb31Sdp	else
1954daaffb31Sdp		wxfile=$argfile
1955daaffb31Sdp	fi
1956daaffb31Sdp
1957cdf0c1d5Smjnelson	$AWK '{ c = 1; print;
1958daaffb31Sdp	  while (getline) {
1959daaffb31Sdp		if (NF == 0) { c = -c; continue }
1960daaffb31Sdp		if (c > 0) print
1961daaffb31Sdp	  }
1962daaffb31Sdp	}' $wxfile > $FLIST
1963daaffb31Sdp
1964daaffb31Sdp	print " Done."
19657c478bd9Sstevel@tonic-gate}
19667c478bd9Sstevel@tonic-gate
19678bcea973SRichard Lowe#
19688bcea973SRichard Lowe# Transform a specified 'git log' output format into a wx-like active list.
19698bcea973SRichard Lowe#
19708bcea973SRichard Lowefunction git_wxfile
19718bcea973SRichard Lowe{
19728bcea973SRichard Lowe	typeset child="$1"
19738bcea973SRichard Lowe	typeset parent="$2"
19748bcea973SRichard Lowe
19758bcea973SRichard Lowe	TMPFLIST=/tmp/$$.active
19768bcea973SRichard Lowe	$PERL -e 'my (%files, %realfiles, $msg);
197744f180b8SYuri Pankov	my $parent = $ARGV[0];
197844f180b8SYuri Pankov	my $child = $ARGV[1];
1979b10a3e23SYuri Pankov
198044f180b8SYuri Pankov	open(F, "git diff -M --name-status $parent..$child |");
19818bcea973SRichard Lowe	while (<F>) {
19828bcea973SRichard Lowe	    chomp;
19838bcea973SRichard Lowe	    if (/^R(\d+)\s+([^ ]+)\s+([^ ]+)/) { # rename
1984b10a3e23SYuri Pankov		if ($1 >= 75) {		 # Probably worth treating as a rename
19853cb02613SRichard Lowe		    $realfiles{$3} = $2;
19868bcea973SRichard Lowe		} else {
19878bcea973SRichard Lowe		    $realfiles{$3} = $3;
19888bcea973SRichard Lowe		    $realfiles{$2} = $2;
1989b10a3e23SYuri Pankov		}
19908bcea973SRichard Lowe	    } else {
19918bcea973SRichard Lowe		my $f = (split /\s+/, $_)[1];
19928bcea973SRichard Lowe		$realfiles{$f} = $f;
19938bcea973SRichard Lowe	    }
19948bcea973SRichard Lowe	}
19958bcea973SRichard Lowe	close(F);
1996b10a3e23SYuri Pankov
19978bcea973SRichard Lowe	my $state = 1;		    # 0|comments, 1|files
199844f180b8SYuri Pankov	open(F, "git whatchanged --pretty=format:%B $parent..$child |");
19998bcea973SRichard Lowe	while (<F>) {
20008bcea973SRichard Lowe	    chomp;
20018bcea973SRichard Lowe	    if (/^:[0-9]{6}/) {
2002b10a3e23SYuri Pankov		my ($unused, $fname, $fname2) = split(/\t/, $_);
2003b10a3e23SYuri Pankov		$fname = $fname2 if defined($fname2);
20048bcea973SRichard Lowe		next if !defined($realfiles{$fname}); # No real change
20058bcea973SRichard Lowe		$state = 1;
20063cb02613SRichard Lowe		chomp $msg;
20073cb02613SRichard Lowe		$files{$fname} .= $msg;
20088bcea973SRichard Lowe	    } else {
20098bcea973SRichard Lowe		if ($state == 1) {
20108bcea973SRichard Lowe		    $state = 0;
20118bcea973SRichard Lowe		    $msg = /^\n/ ? "" : "\n";
20128bcea973SRichard Lowe		}
20138bcea973SRichard Lowe		$msg .= "$_\n" if ($_);
20148bcea973SRichard Lowe	    }
20158bcea973SRichard Lowe	}
20168bcea973SRichard Lowe	close(F);
2017cec8643bSMichal Nowak
20188bcea973SRichard Lowe	for (sort keys %files) {
20198bcea973SRichard Lowe	    if ($realfiles{$_} ne $_) {
20203cb02613SRichard Lowe		print "$_ $realfiles{$_}\n$files{$_}\n\n";
20218bcea973SRichard Lowe	    } else {
20223cb02613SRichard Lowe		print "$_\n$files{$_}\n\n"
20238bcea973SRichard Lowe	    }
202444f180b8SYuri Pankov	}' ${parent} ${child} > $TMPFLIST
20258bcea973SRichard Lowe
20268bcea973SRichard Lowe	wxfile=$TMPFLIST
20278bcea973SRichard Lowe}
20288bcea973SRichard Lowe
20298bcea973SRichard Lowe#
20308bcea973SRichard Lowe# flist_from_git
20318bcea973SRichard Lowe# Build a wx-style active list, and hand it off to flist_from_wx
20328bcea973SRichard Lowe#
20338bcea973SRichard Lowefunction flist_from_git
20348bcea973SRichard Lowe{
20358bcea973SRichard Lowe	typeset child=$1
20368bcea973SRichard Lowe	typeset parent=$2
20378bcea973SRichard Lowe
20388bcea973SRichard Lowe	print " File list from: git ...\c"
20398bcea973SRichard Lowe	git_wxfile "$child" "$parent";
20408bcea973SRichard Lowe
20418bcea973SRichard Lowe	# flist_from_wx prints the Done, so we don't have to.
20428bcea973SRichard Lowe	flist_from_wx $TMPFLIST
20438bcea973SRichard Lowe}
20448bcea973SRichard Lowe
2045daaffb31Sdp#
2046cdf0c1d5Smjnelson# flist_from_subversion
2047daaffb31Sdp#
2048cdf0c1d5Smjnelson# Generate the file list by extracting file names from svn status.
2049daaffb31Sdp#
2050cdf0c1d5Smjnelsonfunction flist_from_subversion
2051daaffb31Sdp{
2052cdf0c1d5Smjnelson	CWS=$1
2053cdf0c1d5Smjnelson	OLDPWD=$2
2054cdf0c1d5Smjnelson
2055cdf0c1d5Smjnelson	cd $CWS
2056cdf0c1d5Smjnelson	print -u2 " File list from: svn status ... \c"
2057cdf0c1d5Smjnelson	svn status | $AWK '/^[ACDMR]/ { print $NF }' > $FLIST
2058cdf0c1d5Smjnelson	print -u2 " Done."
2059cdf0c1d5Smjnelson	cd $OLDPWD
2060cdf0c1d5Smjnelson}
2061cdf0c1d5Smjnelson
2062cdf0c1d5Smjnelsonfunction env_from_flist
2063cdf0c1d5Smjnelson{
2064cdf0c1d5Smjnelson	[[ -r $FLIST ]] || return
2065cdf0c1d5Smjnelson
2066daaffb31Sdp	#
2067cdf0c1d5Smjnelson	# Use "eval" to set env variables that are listed in the file
2068cdf0c1d5Smjnelson	# list.  Then copy those into our local versions of those
2069cdf0c1d5Smjnelson	# variables if they have not been set already.
2070daaffb31Sdp	#
2071b1374179SBill Sommerfeld	eval $($SED -e "s/#.*$//" $FLIST | $GREP = )
2072cdf0c1d5Smjnelson
2073cdf0c1d5Smjnelson	if [[ -z $codemgr_ws && -n $CODEMGR_WS ]]; then
2074cdf0c1d5Smjnelson		codemgr_ws=$CODEMGR_WS
2075cdf0c1d5Smjnelson		export CODEMGR_WS
2076daaffb31Sdp	fi
20777c478bd9Sstevel@tonic-gate
2078daaffb31Sdp	#
2079cdf0c1d5Smjnelson	# Check to see if CODEMGR_PARENT is set in the flist file.
2080daaffb31Sdp	#
2081cdf0c1d5Smjnelson	if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
2082cdf0c1d5Smjnelson		codemgr_parent=$CODEMGR_PARENT
2083cdf0c1d5Smjnelson		export CODEMGR_PARENT
2084daaffb31Sdp	fi
2085daaffb31Sdp}
20867c478bd9Sstevel@tonic-gate
208714983201Sdpfunction look_for_prog
208814983201Sdp{
208914983201Sdp	typeset path
209014983201Sdp	typeset ppath
209114983201Sdp	typeset progname=$1
209214983201Sdp
209314983201Sdp	ppath=$PATH
209414983201Sdp	ppath=$ppath:/usr/sfw/bin:/usr/bin:/usr/sbin
2095d7b56f41SBart Coddens	ppath=$ppath:/opt/onbld/bin
2096b1374179SBill Sommerfeld	ppath=$ppath:/opt/onbld/bin/$(uname -p)
209714983201Sdp
2098b1374179SBill Sommerfeld	PATH=$ppath prog=$(whence $progname)
209914983201Sdp	if [[ -n $prog ]]; then
210014983201Sdp		print $prog
210114983201Sdp	fi
210214983201Sdp}
210314983201Sdp
2104cdf0c1d5Smjnelsonfunction get_file_mode
2105cdf0c1d5Smjnelson{
2106cdf0c1d5Smjnelson	$PERL -e '
2107cdf0c1d5Smjnelson		if (@stat = stat($ARGV[0])) {
2108cdf0c1d5Smjnelson			$mode = $stat[2] & 0777;
2109cdf0c1d5Smjnelson			printf "%03o\n", $mode;
2110cdf0c1d5Smjnelson			exit 0;
2111cdf0c1d5Smjnelson		} else {
2112cdf0c1d5Smjnelson			exit 1;
2113cdf0c1d5Smjnelson		}
2114cdf0c1d5Smjnelson	    ' $1
2115cdf0c1d5Smjnelson}
2116cdf0c1d5Smjnelson
21178bcea973SRichard Lowefunction build_old_new_git
21188bcea973SRichard Lowe{
21198bcea973SRichard Lowe	typeset olddir="$1"
21208bcea973SRichard Lowe	typeset newdir="$2"
21218bcea973SRichard Lowe	typeset o_mode=
21228bcea973SRichard Lowe	typeset n_mode=
21238bcea973SRichard Lowe	typeset o_object=
21248bcea973SRichard Lowe	typeset n_object=
21258bcea973SRichard Lowe	typeset OWD=$PWD
21268bcea973SRichard Lowe	typeset file
21278bcea973SRichard Lowe	typeset type
21288bcea973SRichard Lowe
21298bcea973SRichard Lowe	cd $CWS
21308bcea973SRichard Lowe
21318bcea973SRichard Lowe	#
21328bcea973SRichard Lowe	# Get old file and its mode from the git object tree
21338bcea973SRichard Lowe	#
21348bcea973SRichard Lowe	if [[ "$PDIR" == "." ]]; then
21358bcea973SRichard Lowe		file="$PF"
21368bcea973SRichard Lowe	else
2137b0efaad7SJoshua M. Clulow		file="$PDIR/$PF"
21388bcea973SRichard Lowe	fi
21398bcea973SRichard Lowe
21408bcea973SRichard Lowe	if [[ -n $parent_webrev && -e $PWS/$PDIR/$PF ]]; then
21418bcea973SRichard Lowe		cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
21428bcea973SRichard Lowe	else
2143b0efaad7SJoshua M. Clulow		$GIT ls-tree $GIT_PARENT $file | read o_mode type o_object junk
2144b0efaad7SJoshua M. Clulow		$GIT cat-file $type $o_object > $olddir/$file 2>/dev/null
2145b0efaad7SJoshua M. Clulow
2146b0efaad7SJoshua M. Clulow		if (( $? != 0 )); then
2147b0efaad7SJoshua M. Clulow			rm -f $olddir/$file
2148b0efaad7SJoshua M. Clulow		elif [[ -n $o_mode ]]; then
2149b0efaad7SJoshua M. Clulow			# Strip the first 3 digits, to get a regular octal mode
2150b0efaad7SJoshua M. Clulow			o_mode=${o_mode/???/}
2151b0efaad7SJoshua M. Clulow			chmod $o_mode $olddir/$file
2152b0efaad7SJoshua M. Clulow		else
2153b0efaad7SJoshua M. Clulow			# should never happen
2154b0efaad7SJoshua M. Clulow			print -u2 "ERROR: set mode of $olddir/$file"
2155b0efaad7SJoshua M. Clulow		fi
21568bcea973SRichard Lowe	fi
21578bcea973SRichard Lowe
21588bcea973SRichard Lowe	#
21598bcea973SRichard Lowe	# new version of the file.
21608bcea973SRichard Lowe	#
21618bcea973SRichard Lowe	if [[ "$DIR" == "." ]]; then
21628bcea973SRichard Lowe		file="$F"
21638bcea973SRichard Lowe	else
21648bcea973SRichard Lowe		file="$DIR/$F"
21658bcea973SRichard Lowe	fi
21668bcea973SRichard Lowe	rm -rf $newdir/$file
21678bcea973SRichard Lowe
21688bcea973SRichard Lowe        if [[ -e $CWS/$DIR/$F ]]; then
2169b0efaad7SJoshua M. Clulow		cp $CWS/$DIR/$F $newdir/$DIR/$F
2170b0efaad7SJoshua M. Clulow		chmod $(get_file_mode $CWS/$DIR/$F) $newdir/$DIR/$F
21718bcea973SRichard Lowe        fi
21728bcea973SRichard Lowe	cd $OWD
21738bcea973SRichard Lowe}
21748bcea973SRichard Lowe
2175cdf0c1d5Smjnelsonfunction build_old_new_subversion
2176cdf0c1d5Smjnelson{
2177cdf0c1d5Smjnelson	typeset olddir="$1"
2178cdf0c1d5Smjnelson	typeset newdir="$2"
2179cdf0c1d5Smjnelson
2180cdf0c1d5Smjnelson	# Snag new version of file.
2181cdf0c1d5Smjnelson	rm -f $newdir/$DIR/$F
2182cdf0c1d5Smjnelson	[[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F
2183cdf0c1d5Smjnelson
2184cdf0c1d5Smjnelson	if [[ -n $PWS && -e $PWS/$PDIR/$PF ]]; then
2185cdf0c1d5Smjnelson		cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
2186cdf0c1d5Smjnelson	else
2187cdf0c1d5Smjnelson		# Get the parent's version of the file.
2188cdf0c1d5Smjnelson		svn status $CWS/$DIR/$F | read stat file
2189cdf0c1d5Smjnelson		if [[ $stat != "A" ]]; then
2190cdf0c1d5Smjnelson			svn cat -r BASE $CWS/$DIR/$F > $olddir/$PDIR/$PF
2191cdf0c1d5Smjnelson		fi
2192cdf0c1d5Smjnelson	fi
2193cdf0c1d5Smjnelson}
2194cdf0c1d5Smjnelson
2195cdf0c1d5Smjnelsonfunction build_old_new_unknown
2196cdf0c1d5Smjnelson{
2197cdf0c1d5Smjnelson	typeset olddir="$1"
2198cdf0c1d5Smjnelson	typeset newdir="$2"
2199cdf0c1d5Smjnelson
2200cdf0c1d5Smjnelson	#
2201cdf0c1d5Smjnelson	# Snag new version of file.
2202cdf0c1d5Smjnelson	#
2203cdf0c1d5Smjnelson	rm -f $newdir/$DIR/$F
2204cdf0c1d5Smjnelson	[[ -e $CWS/$DIR/$F ]] && cp $CWS/$DIR/$F $newdir/$DIR/$F
2205cdf0c1d5Smjnelson
2206cdf0c1d5Smjnelson	#
2207cdf0c1d5Smjnelson	# Snag the parent's version of the file.
2208e6ccc173SEdward Pilatowicz	#
2209cdf0c1d5Smjnelson	if [[ -f $PWS/$PDIR/$PF ]]; then
2210cdf0c1d5Smjnelson		rm -f $olddir/$PDIR/$PF
2211cdf0c1d5Smjnelson		cp $PWS/$PDIR/$PF $olddir/$PDIR/$PF
2212cdf0c1d5Smjnelson	fi
2213cdf0c1d5Smjnelson}
2214cdf0c1d5Smjnelson
2215cdf0c1d5Smjnelsonfunction build_old_new
2216cdf0c1d5Smjnelson{
2217cdf0c1d5Smjnelson	typeset WDIR=$1
2218cdf0c1d5Smjnelson	typeset PWS=$2
2219cdf0c1d5Smjnelson	typeset PDIR=$3
2220cdf0c1d5Smjnelson	typeset PF=$4
2221cdf0c1d5Smjnelson	typeset CWS=$5
2222cdf0c1d5Smjnelson	typeset DIR=$6
2223cdf0c1d5Smjnelson	typeset F=$7
2224cdf0c1d5Smjnelson
2225cdf0c1d5Smjnelson	typeset olddir="$WDIR/raw_files/old"
2226cdf0c1d5Smjnelson	typeset newdir="$WDIR/raw_files/new"
2227cdf0c1d5Smjnelson
2228cdf0c1d5Smjnelson	mkdir -p $olddir/$PDIR
2229cdf0c1d5Smjnelson	mkdir -p $newdir/$DIR
2230cdf0c1d5Smjnelson
22310f554fe5SRichard Lowe	if [[ $SCM_MODE == "git" ]]; then
22328bcea973SRichard Lowe		build_old_new_git "$olddir" "$newdir"
2233cdf0c1d5Smjnelson	elif [[ $SCM_MODE == "subversion" ]]; then
2234cdf0c1d5Smjnelson		build_old_new_subversion "$olddir" "$newdir"
2235cdf0c1d5Smjnelson	elif [[ $SCM_MODE == "unknown" ]]; then
2236cdf0c1d5Smjnelson		build_old_new_unknown "$olddir" "$newdir"
2237cdf0c1d5Smjnelson	fi
2238cdf0c1d5Smjnelson
2239cdf0c1d5Smjnelson	if [[ ! -f $olddir/$PDIR/$PF && ! -f $newdir/$DIR/$F ]]; then
2240cdf0c1d5Smjnelson		print "*** Error: file not in parent or child"
2241cdf0c1d5Smjnelson		return 1
2242cdf0c1d5Smjnelson	fi
2243cdf0c1d5Smjnelson	return 0
2244cdf0c1d5Smjnelson}
2245cdf0c1d5Smjnelson
2246cdf0c1d5Smjnelson
2247daaffb31Sdp#
2248daaffb31Sdp# Usage message.
2249daaffb31Sdp#
2250daaffb31Sdpfunction usage
2251daaffb31Sdp{
2252daaffb31Sdp	print 'Usage:\twebrev [common-options]
2253daaffb31Sdp	webrev [common-options] ( <file> | - )
2254daaffb31Sdp	webrev [common-options] -w <wx file>
2255daaffb31Sdp
2256daaffb31SdpOptions:
225744f180b8SYuri Pankov	-c <revision>: generate webrev for single revision (git only)
22580fd2682eSMark J. Nelson	-C <filename>: Use <filename> for the information tracking configuration.
2259ba44d8a2SVladimir Kotal	-D: delete remote webrev
226044f180b8SYuri Pankov	-h <revision>: specify "head" revision for comparison (git only)
2261daaffb31Sdp	-i <filename>: Include <filename> in the index.html file.
22620fd2682eSMark J. Nelson	-I <filename>: Use <filename> for the information tracking registry.
2263ba44d8a2SVladimir Kotal	-n: do not generate the webrev (useful with -U)
2264ba44d8a2SVladimir Kotal	-O: Print bugids/arc cases suitable for OpenSolaris.
2265daaffb31Sdp	-o <outdir>: Output webrev to specified directory.
2266daaffb31Sdp	-p <compare-against>: Use specified parent wkspc or basis for comparison
226702d26c39SVladimir Kotal	-t <remote_target>: Specify remote destination for webrev upload
226802d26c39SVladimir Kotal	-U: upload the webrev to remote destination
2269daaffb31Sdp	-w <wxfile>: Use specified wx active file.
2270daaffb31Sdp
2271daaffb31SdpEnvironment:
2272daaffb31Sdp	WDIR: Control the output directory.
2273ba44d8a2SVladimir Kotal	WEBREV_TRASH_DIR: Set directory for webrev delete.
2274daaffb31Sdp
2275daaffb31SdpSCM Environment:
2276cdf0c1d5Smjnelson	CODEMGR_WS: Workspace location.
2277cdf0c1d5Smjnelson	CODEMGR_PARENT: Parent workspace location.
2278daaffb31Sdp'
2279daaffb31Sdp
2280daaffb31Sdp	exit 2
2281daaffb31Sdp}
2282daaffb31Sdp
2283daaffb31Sdp#
2284daaffb31Sdp#
2285daaffb31Sdp# Main program starts here
2286daaffb31Sdp#
2287daaffb31Sdp#
2288daaffb31Sdp
2289daaffb31Sdptrap "rm -f /tmp/$$.* ; exit" 0 1 2 3 15
2290daaffb31Sdp
2291daaffb31Sdpset +o noclobber
2292daaffb31Sdp
22938bcea973SRichard LowePATH=$(/bin/dirname "$(whence $0)"):$PATH
2294cdf0c1d5Smjnelson
2295b1374179SBill Sommerfeld[[ -z $WDIFF ]] && WDIFF=$(look_for_prog wdiff)
2296b1374179SBill Sommerfeld[[ -z $WX ]] && WX=$(look_for_prog wx)
2297b1374179SBill Sommerfeld[[ -z $GIT ]] && GIT=$(look_for_prog git)
2298b1374179SBill Sommerfeld[[ -z $WHICH_SCM ]] && WHICH_SCM=$(look_for_prog which_scm)
2299b1374179SBill Sommerfeld[[ -z $PERL ]] && PERL=$(look_for_prog perl)
2300b1374179SBill Sommerfeld[[ -z $RSYNC ]] && RSYNC=$(look_for_prog rsync)
2301b1374179SBill Sommerfeld[[ -z $SCCS ]] && SCCS=$(look_for_prog sccs)
2302b1374179SBill Sommerfeld[[ -z $AWK ]] && AWK=$(look_for_prog nawk)
2303b1374179SBill Sommerfeld[[ -z $AWK ]] && AWK=$(look_for_prog gawk)
2304b1374179SBill Sommerfeld[[ -z $AWK ]] && AWK=$(look_for_prog awk)
2305b1374179SBill Sommerfeld[[ -z $SCP ]] && SCP=$(look_for_prog scp)
2306b1374179SBill Sommerfeld[[ -z $SED ]] && SED=$(look_for_prog sed)
2307b1374179SBill Sommerfeld[[ -z $SFTP ]] && SFTP=$(look_for_prog sftp)
2308b1374179SBill Sommerfeld[[ -z $SORT ]] && SORT=$(look_for_prog sort)
2309b1374179SBill Sommerfeld[[ -z $MKTEMP ]] && MKTEMP=$(look_for_prog mktemp)
2310b1374179SBill Sommerfeld[[ -z $GREP ]] && GREP=$(look_for_prog grep)
2311b1374179SBill Sommerfeld[[ -z $FIND ]] && FIND=$(look_for_prog find)
2312b1374179SBill Sommerfeld[[ -z $MANDOC ]] && MANDOC=$(look_for_prog mandoc)
2313b1374179SBill Sommerfeld[[ -z $COL ]] && COL=$(look_for_prog col)
2314cdf0c1d5Smjnelson
2315ba44d8a2SVladimir Kotal# set name of trash directory for remote webrev deletion
2316ba44d8a2SVladimir KotalTRASH_DIR=".trash"
2317ba44d8a2SVladimir Kotal[[ -n $WEBREV_TRASH_DIR ]] && TRASH_DIR=$WEBREV_TRASH_DIR
231814983201Sdp
231914983201Sdpif [[ ! -x $PERL ]]; then
232014983201Sdp	print -u2 "Error: No perl interpreter found.  Exiting."
232114983201Sdp	exit 1
23227c478bd9Sstevel@tonic-gatefi
23237c478bd9Sstevel@tonic-gate
2324cdf0c1d5Smjnelsonif [[ ! -x $WHICH_SCM ]]; then
2325cdf0c1d5Smjnelson	print -u2 "Error: Could not find which_scm.  Exiting."
2326cdf0c1d5Smjnelson	exit 1
2327cdf0c1d5Smjnelsonfi
2328cdf0c1d5Smjnelson
232914983201Sdp[[ ! -x $WDIFF ]] && print -u2 "WARNING: wdiff not found."
233014983201Sdp
2331daaffb31Sdp# Declare global total counters.
2332daaffb31Sdpinteger TOTL TINS TDEL TMOD TUNC
2333daaffb31Sdp
2334ba44d8a2SVladimir Kotal# default remote host for upload/delete
2335ba44d8a2SVladimir Kotaltypeset -r DEFAULT_REMOTE_HOST="cr.opensolaris.org"
2336b0088928SVladimir Kotal# prefixes for upload targets
2337b0088928SVladimir Kotaltypeset -r rsync_prefix="rsync://"
2338b0088928SVladimir Kotaltypeset -r ssh_prefix="ssh://"
2339ba44d8a2SVladimir Kotal
234044f180b8SYuri Pankovcflag=
23410fd2682eSMark J. NelsonCflag=
2342ba44d8a2SVladimir KotalDflag=
234314983201Sdpflist_mode=
234414983201Sdpflist_file=
234544f180b8SYuri Pankovhflag=
2346daaffb31Sdpiflag=
23470fd2682eSMark J. NelsonIflag=
234802d26c39SVladimir Kotallflag=
234902d26c39SVladimir KotalNflag=
235002d26c39SVladimir Kotalnflag=
235102d26c39SVladimir KotalOflag=
2352daaffb31Sdpoflag=
2353daaffb31Sdppflag=
235402d26c39SVladimir Kotaltflag=
235502d26c39SVladimir Kotaluflag=
235602d26c39SVladimir KotalUflag=
2357daaffb31Sdpwflag=
235802d26c39SVladimir Kotalremote_target=
2359ba44d8a2SVladimir Kotal
236044f180b8SYuri Pankovwhile getopts "c:C:Dh:i:I:lnNo:Op:t:Uw" opt
2361daaffb31Sdpdo
2362daaffb31Sdp	case $opt in
236344f180b8SYuri Pankov	c)	cflag=1
236444f180b8SYuri Pankov		codemgr_head=$OPTARG
236544f180b8SYuri Pankov		codemgr_parent=$OPTARG~1;;
236644f180b8SYuri Pankov
23670fd2682eSMark J. Nelson	C)	Cflag=1
23680fd2682eSMark J. Nelson		ITSCONF=$OPTARG;;
23690fd2682eSMark J. Nelson
2370ba44d8a2SVladimir Kotal	D)	Dflag=1;;
2371ba44d8a2SVladimir Kotal
237244f180b8SYuri Pankov	h)	hflag=1
237344f180b8SYuri Pankov		codemgr_head=$OPTARG;;
237444f180b8SYuri Pankov
2375daaffb31Sdp	i)	iflag=1
2376daaffb31Sdp		INCLUDE_FILE=$OPTARG;;
2377daaffb31Sdp
23780fd2682eSMark J. Nelson	I)	Iflag=1
23790fd2682eSMark J. Nelson		ITSREG=$OPTARG;;
23800fd2682eSMark J. Nelson
238102d26c39SVladimir Kotal	N)	Nflag=1;;
238202d26c39SVladimir Kotal
238302d26c39SVladimir Kotal	n)	nflag=1;;
23847c478bd9Sstevel@tonic-gate
2385daaffb31Sdp	O)	Oflag=1;;
23867c478bd9Sstevel@tonic-gate
238702d26c39SVladimir Kotal	o)	oflag=1
23889d3952abSVladimir Kotal		# Strip the trailing slash to correctly form remote target.
23899d3952abSVladimir Kotal		WDIR=${OPTARG%/};;
239002d26c39SVladimir Kotal
239102d26c39SVladimir Kotal	p)	pflag=1
239202d26c39SVladimir Kotal		codemgr_parent=$OPTARG;;
239302d26c39SVladimir Kotal
239402d26c39SVladimir Kotal	t)	tflag=1
239502d26c39SVladimir Kotal		remote_target=$OPTARG;;
239602d26c39SVladimir Kotal
239702d26c39SVladimir Kotal	U)	Uflag=1;;
239802d26c39SVladimir Kotal
239902d26c39SVladimir Kotal	w)	wflag=1;;
24003df69ef3SDarren Moffat
2401daaffb31Sdp	?)	usage;;
2402daaffb31Sdp	esac
2403daaffb31Sdpdone
2404daaffb31Sdp
2405daaffb31SdpFLIST=/tmp/$$.flist
2406daaffb31Sdp
2407daaffb31Sdpif [[ -n $wflag && -n $lflag ]]; then
2408daaffb31Sdp	usage
24097c478bd9Sstevel@tonic-gatefi
24107c478bd9Sstevel@tonic-gate
241102d26c39SVladimir Kotal# more sanity checking
241202d26c39SVladimir Kotalif [[ -n $nflag && -z $Uflag ]]; then
2413ba44d8a2SVladimir Kotal	print "it does not make sense to skip webrev generation" \
2414ba44d8a2SVladimir Kotal	    "without -U"
241502d26c39SVladimir Kotal	exit 1
241602d26c39SVladimir Kotalfi
241702d26c39SVladimir Kotal
2418ba44d8a2SVladimir Kotalif [[ -n $tflag && -z $Uflag && -z $Dflag ]]; then
2419ba44d8a2SVladimir Kotal	echo "remote target has to be used only for upload or delete"
242002d26c39SVladimir Kotal	exit 1
242102d26c39SVladimir Kotalfi
242202d26c39SVladimir Kotal
24232d9224a3SMark J. Nelson#
24242d9224a3SMark J. Nelson# For the invocation "webrev -n -U" with no other options, webrev will assume
24252d9224a3SMark J. Nelson# that the webrev exists in ${CWS}/webrev, but will upload it using the name
24262d9224a3SMark J. Nelson# $(basename ${CWS}).  So we need to get CWS set before we skip any remaining
24272d9224a3SMark J. Nelson# logic.
24282d9224a3SMark J. Nelson#
24292d9224a3SMark J. Nelson$WHICH_SCM | read SCM_MODE junk || exit 1
24300f554fe5SRichard Lowe
24310f554fe5SRichard Loweif [[ $SCM_MODE == "git" ]]; then
24328bcea973SRichard Lowe	#
24338bcea973SRichard Lowe	# Git priorities:
2434*9af2fe54SBill Sommerfeld	# 1. git rev-parse --show-toplevel from CODEMGR_WS environment variable
2435*9af2fe54SBill Sommerfeld	# 2. git rev-parse --show-toplevel from directory of invocation
24368bcea973SRichard Lowe	#
24378bcea973SRichard Lowe	[[ -z $codemgr_ws && -n $CODEMGR_WS ]] && \
2438*9af2fe54SBill Sommerfeld	    codemgr_ws=$($GIT -C $CODEMGR_WS rev-parse --show-toplevel \
2439b0efaad7SJoshua M. Clulow		2>/dev/null)
24408bcea973SRichard Lowe	[[ -z $codemgr_ws ]] && \
2441*9af2fe54SBill Sommerfeld	    codemgr_ws=$($GIT rev-parse --show-toplevel 2>/dev/null)
24428bcea973SRichard Lowe
24438bcea973SRichard Lowe	CWS="$codemgr_ws"
24442d9224a3SMark J. Nelsonelif [[ $SCM_MODE == "subversion" ]]; then
24452d9224a3SMark J. Nelson	#
24462d9224a3SMark J. Nelson	# Subversion priorities:
24472d9224a3SMark J. Nelson	# 1. CODEMGR_WS from environment
24482d9224a3SMark J. Nelson	# 2. Relative path from current directory to SVN repository root
24492d9224a3SMark J. Nelson	#
24502d9224a3SMark J. Nelson	if [[ -n $CODEMGR_WS && -d $CODEMGR_WS/.svn ]]; then
24512d9224a3SMark J. Nelson		CWS=$CODEMGR_WS
24522d9224a3SMark J. Nelson	else
24532d9224a3SMark J. Nelson		svn info | while read line; do
24542d9224a3SMark J. Nelson			if [[ $line == "URL: "* ]]; then
24552d9224a3SMark J. Nelson				url=${line#URL: }
24562d9224a3SMark J. Nelson			elif [[ $line == "Repository Root: "* ]]; then
24572d9224a3SMark J. Nelson				repo=${line#Repository Root: }
24582d9224a3SMark J. Nelson			fi
24592d9224a3SMark J. Nelson		done
24602d9224a3SMark J. Nelson
2461e6ccc173SEdward Pilatowicz		rel=${url#$repo}
24622d9224a3SMark J. Nelson		CWS=${PWD%$rel}
24632d9224a3SMark J. Nelson	fi
24642d9224a3SMark J. Nelsonfi
24652d9224a3SMark J. Nelson
24662d9224a3SMark J. Nelson#
24672d9224a3SMark J. Nelson# If no SCM has been determined, take either the environment setting
24682d9224a3SMark J. Nelson# setting for CODEMGR_WS, or the current directory if that wasn't set.
24692d9224a3SMark J. Nelson#
24702d9224a3SMark J. Nelsonif [[ -z ${CWS} ]]; then
24712d9224a3SMark J. Nelson	CWS=${CODEMGR_WS:-.}
24722d9224a3SMark J. Nelsonfi
24732d9224a3SMark J. Nelson
24740fd2682eSMark J. Nelson#
24750fd2682eSMark J. Nelson# If the command line options indicate no webrev generation, either
24760fd2682eSMark J. Nelson# explicitly (-n) or implicitly (-D but not -U), then there's a whole
24770fd2682eSMark J. Nelson# ton of logic we can skip.
24780fd2682eSMark J. Nelson#
24790fd2682eSMark J. Nelson# Instead of increasing indentation, we intentionally leave this loop
24800fd2682eSMark J. Nelson# body open here, and exit via break from multiple points within.
24810fd2682eSMark J. Nelson# Search for DO_EVERYTHING below to find the break points and closure.
24820fd2682eSMark J. Nelson#
24830fd2682eSMark J. Nelsonfor do_everything in 1; do
24840fd2682eSMark J. Nelson
24850fd2682eSMark J. Nelson# DO_EVERYTHING: break point
24860fd2682eSMark J. Nelsonif [[ -n $nflag || ( -z $Uflag && -n $Dflag ) ]]; then
24870fd2682eSMark J. Nelson	break
24880fd2682eSMark J. Nelsonfi
24890fd2682eSMark J. Nelson
2490daaffb31Sdp#
2491daaffb31Sdp# If this manually set as the parent, and it appears to be an earlier webrev,
2492daaffb31Sdp# then note that fact and set the parent to the raw_files/new subdirectory.
2493daaffb31Sdp#
2494daaffb31Sdpif [[ -n $pflag && -d $codemgr_parent/raw_files/new ]]; then
24958bcea973SRichard Lowe	parent_webrev=$(readlink -f "$codemgr_parent")
24968bcea973SRichard Lowe	codemgr_parent=$(readlink -f "$codemgr_parent/raw_files/new")
2497daaffb31Sdpfi
24987c478bd9Sstevel@tonic-gate
2499daaffb31Sdpif [[ -z $wflag && -z $lflag ]]; then
2500daaffb31Sdp	shift $(($OPTIND - 1))
25017c478bd9Sstevel@tonic-gate
2502daaffb31Sdp	if [[ $1 == "-" ]]; then
2503daaffb31Sdp		cat > $FLIST
250414983201Sdp		flist_mode="stdin"
250514983201Sdp		flist_done=1
250614983201Sdp		shift
2507daaffb31Sdp	elif [[ -n $1 ]]; then
250814983201Sdp		if [[ ! -r $1 ]]; then
2509daaffb31Sdp			print -u2 "$1: no such file or not readable"
2510daaffb31Sdp			usage
2511daaffb31Sdp		fi
2512daaffb31Sdp		cat $1 > $FLIST
251314983201Sdp		flist_mode="file"
251414983201Sdp		flist_file=$1
251514983201Sdp		flist_done=1
251614983201Sdp		shift
2517daaffb31Sdp	else
251814983201Sdp		flist_mode="auto"
2519daaffb31Sdp	fi
25207c478bd9Sstevel@tonic-gatefi
2521daaffb31Sdp
2522daaffb31Sdp#
2523daaffb31Sdp# Before we go on to further consider -l and -w, work out which SCM we think
2524daaffb31Sdp# is in use.
2525daaffb31Sdp#
2526cdf0c1d5Smjnelsoncase "$SCM_MODE" in
25270f554fe5SRichard Lowegit|subversion)
2528cdf0c1d5Smjnelson	;;
2529cdf0c1d5Smjnelsonunknown)
2530cdf0c1d5Smjnelson	if [[ $flist_mode == "auto" ]]; then
2531cdf0c1d5Smjnelson		print -u2 "Unable to determine SCM in use and file list not specified"
2532cdf0c1d5Smjnelson		print -u2 "See which_scm(1) for SCM detection information."
2533cdf0c1d5Smjnelson		exit 1
2534cdf0c1d5Smjnelson	fi
2535cdf0c1d5Smjnelson	;;
2536cdf0c1d5Smjnelson*)
2537cdf0c1d5Smjnelson	if [[ $flist_mode == "auto" ]]; then
2538cdf0c1d5Smjnelson		print -u2 "Unsupported SCM in use ($SCM_MODE) and file list not specified"
2539cdf0c1d5Smjnelson		exit 1
2540cdf0c1d5Smjnelson	fi
2541cdf0c1d5Smjnelson	;;
2542cdf0c1d5Smjnelsonesac
25437c478bd9Sstevel@tonic-gate
2544daaffb31Sdpprint -u2 "   SCM detected: $SCM_MODE"
25457c478bd9Sstevel@tonic-gate
2546d7b56f41SBart Coddensif [[ -n $wflag ]]; then
2547daaffb31Sdp	#
2548daaffb31Sdp	# If the -w is given then assume the file list is in Bonwick's "wx"
2549daaffb31Sdp	# command format, i.e.  pathname lines alternating with SCCS comment
2550daaffb31Sdp	# lines with blank lines as separators.  Use the SCCS comments later
2551daaffb31Sdp	# in building the index.html file.
2552daaffb31Sdp	#
2553daaffb31Sdp	shift $(($OPTIND - 1))
2554daaffb31Sdp	wxfile=$1
2555daaffb31Sdp	if [[ -z $wxfile && -n $CODEMGR_WS ]]; then
2556daaffb31Sdp		if [[ -r $CODEMGR_WS/wx/active ]]; then
2557daaffb31Sdp			wxfile=$CODEMGR_WS/wx/active
2558daaffb31Sdp		fi
2559daaffb31Sdp	fi
25607c478bd9Sstevel@tonic-gate
2561daaffb31Sdp	[[ -z $wxfile ]] && print -u2 "wx file not specified, and could not " \
2562daaffb31Sdp	    "be auto-detected (check \$CODEMGR_WS)" && exit 1
25637c478bd9Sstevel@tonic-gate
2564cdf0c1d5Smjnelson	if [[ ! -r $wxfile ]]; then
2565cdf0c1d5Smjnelson		print -u2 "$wxfile: no such file or not readable"
2566cdf0c1d5Smjnelson		usage
2567cdf0c1d5Smjnelson	fi
2568cdf0c1d5Smjnelson
2569daaffb31Sdp	print -u2 " File list from: wx 'active' file '$wxfile' ... \c"
2570daaffb31Sdp	flist_from_wx $wxfile
2571daaffb31Sdp	flist_done=1
2572daaffb31Sdp	if [[ -n "$*" ]]; then
2573daaffb31Sdp		shift
2574daaffb31Sdp	fi
257514983201Sdpelif [[ $flist_mode == "stdin" ]]; then
257614983201Sdp	print -u2 " File list from: standard input"
257714983201Sdpelif [[ $flist_mode == "file" ]]; then
257814983201Sdp	print -u2 " File list from: $flist_file"
25797c478bd9Sstevel@tonic-gatefi
25807c478bd9Sstevel@tonic-gate
2581b1374179SBill Sommerfeldif (( $# > 0 )); then
258214983201Sdp	print -u2 "WARNING: unused arguments: $*"
25837c478bd9Sstevel@tonic-gatefi
25847c478bd9Sstevel@tonic-gate
25858bcea973SRichard Lowe
25860f554fe5SRichard Loweif [[ $SCM_MODE == "git" ]]; then
258744f180b8SYuri Pankov	# Check that "head" revision specified with -c or -h is sane
258844f180b8SYuri Pankov	if [[ -n $cflag || -n $hflag ]]; then
258944f180b8SYuri Pankov		head_rev=$($GIT rev-parse --verify --quiet "$codemgr_head")
259044f180b8SYuri Pankov		if [[ -z $head_rev ]]; then
259144f180b8SYuri Pankov			print -u2 "Error: bad revision ${codemgr_head}"
259244f180b8SYuri Pankov			exit 1
259344f180b8SYuri Pankov		fi
259444f180b8SYuri Pankov	fi
259544f180b8SYuri Pankov
259644f180b8SYuri Pankov	if [[ -z $codemgr_head ]]; then
259744f180b8SYuri Pankov		codemgr_head="HEAD";
259844f180b8SYuri Pankov	fi
259944f180b8SYuri Pankov
26008bcea973SRichard Lowe	# Parent can either be specified with -p, or specified with
26018bcea973SRichard Lowe	# CODEMGR_PARENT in the environment.
26028bcea973SRichard Lowe	if [[ -z $codemgr_parent && -n $CODEMGR_PARENT ]]; then
26038bcea973SRichard Lowe		codemgr_parent=$CODEMGR_PARENT
26048bcea973SRichard Lowe	fi
26058bcea973SRichard Lowe
26068bcea973SRichard Lowe	# Try to figure out the parent based on the branch the current
26078bcea973SRichard Lowe	# branch is tracking, if we fail, use origin/master
26088bcea973SRichard Lowe	this_branch=$($GIT branch | nawk '$1 == "*" { print $2 }')
26098bcea973SRichard Lowe	par_branch="origin/master"
26108bcea973SRichard Lowe
2611b0efaad7SJoshua M. Clulow	# If we're not on a branch there's nothing we can do
2612b0efaad7SJoshua M. Clulow	if [[ $this_branch != "(no branch)" ]]; then
2613b0efaad7SJoshua M. Clulow		$GIT for-each-ref					\
2614b0efaad7SJoshua M. Clulow		    --format='%(refname:short) %(upstream:short)'	\
2615b0efaad7SJoshua M. Clulow		    refs/heads/ |					\
2616b0efaad7SJoshua M. Clulow		    while read local remote; do
2617b0efaad7SJoshua M. Clulow			if [[ "$local" == "$this_branch" ]]; then
2618b0efaad7SJoshua M. Clulow				par_branch="$remote"
2619b0efaad7SJoshua M. Clulow			fi
2620b0efaad7SJoshua M. Clulow		done
26218bcea973SRichard Lowe	fi
26228bcea973SRichard Lowe
26238bcea973SRichard Lowe	if [[ -z $codemgr_parent ]]; then
26248bcea973SRichard Lowe		codemgr_parent=$par_branch
26258bcea973SRichard Lowe	fi
26268bcea973SRichard Lowe	PWS=$codemgr_parent
26278bcea973SRichard Lowe
26288bcea973SRichard Lowe	#
26298bcea973SRichard Lowe	# If the parent is a webrev, we want to do some things against
26308bcea973SRichard Lowe	# the natural workspace parent (file list, comments, etc)
26318bcea973SRichard Lowe	#
26328bcea973SRichard Lowe	if [[ -n $parent_webrev ]]; then
26338bcea973SRichard Lowe		real_parent=$par_branch
26348bcea973SRichard Lowe	else
26358bcea973SRichard Lowe		real_parent=$PWS
26368bcea973SRichard Lowe	fi
26378bcea973SRichard Lowe
26388bcea973SRichard Lowe	if [[ -z $flist_done ]]; then
263944f180b8SYuri Pankov		flist_from_git "$codemgr_head" "$real_parent"
26408bcea973SRichard Lowe		flist_done=1
26418bcea973SRichard Lowe	fi
26428bcea973SRichard Lowe
26438bcea973SRichard Lowe	#
26448bcea973SRichard Lowe	# If we have a file list now, pull out any variables set
26458bcea973SRichard Lowe	# therein.
26468bcea973SRichard Lowe	#
26478bcea973SRichard Lowe	if [[ -n $flist_done ]]; then
26488bcea973SRichard Lowe		env_from_flist
26498bcea973SRichard Lowe	fi
26508bcea973SRichard Lowe
26518bcea973SRichard Lowe	#
26528bcea973SRichard Lowe	# If we don't have a wx-format file list, build one we can pull change
26538bcea973SRichard Lowe	# comments from.
26548bcea973SRichard Lowe	#
26558bcea973SRichard Lowe	if [[ -z $wxfile ]]; then
26568bcea973SRichard Lowe		print "  Comments from: git...\c"
265744f180b8SYuri Pankov		git_wxfile "$codemgr_head" "$real_parent"
26588bcea973SRichard Lowe		print " Done."
26598bcea973SRichard Lowe	fi
26608bcea973SRichard Lowe
26618bcea973SRichard Lowe	if [[ -z $GIT_PARENT ]]; then
266244f180b8SYuri Pankov		GIT_PARENT=$($GIT merge-base "$real_parent" "$codemgr_head")
26638bcea973SRichard Lowe	fi
26648bcea973SRichard Lowe	if [[ -z $GIT_PARENT ]]; then
26658bcea973SRichard Lowe		print -u2 "Error: Cannot discover parent revision"
26668bcea973SRichard Lowe		exit 1
26678bcea973SRichard Lowe	fi
26688bcea973SRichard Lowe
26698bcea973SRichard Lowe	pnode=$(trim_digest $GIT_PARENT)
26708bcea973SRichard Lowe
267144f180b8SYuri Pankov	if [[ -n $cflag ]]; then
267244f180b8SYuri Pankov		PRETTY_PWS="previous revision (at ${pnode})"
267344f180b8SYuri Pankov	elif [[ $real_parent == */* ]]; then
26748bcea973SRichard Lowe		origin=$(echo $real_parent | cut -d/ -f1)
26758bcea973SRichard Lowe		origin=$($GIT remote -v | \
26768bcea973SRichard Lowe		    $AWK '$1 == "'$origin'" { print $2; exit }')
26778bcea973SRichard Lowe		PRETTY_PWS="${PWS} (${origin} at ${pnode})"
267844f180b8SYuri Pankov	elif [[ -n $pflag && -z $parent_webrev ]]; then
267944f180b8SYuri Pankov		PRETTY_PWS="${CWS} (explicit revision ${pnode})"
26808bcea973SRichard Lowe	else
26818bcea973SRichard Lowe		PRETTY_PWS="${PWS} (at ${pnode})"
26828bcea973SRichard Lowe	fi
26838bcea973SRichard Lowe
268444f180b8SYuri Pankov	cnode=$($GIT --git-dir=${codemgr_ws}/.git rev-parse --short=12 \
268544f180b8SYuri Pankov	    ${codemgr_head} 2>/dev/null)
268644f180b8SYuri Pankov
268744f180b8SYuri Pankov	if [[ -n $cflag || -n $hflag ]]; then
268844f180b8SYuri Pankov		PRETTY_CWS="${CWS} (explicit head at ${cnode})"
268944f180b8SYuri Pankov	else
269044f180b8SYuri Pankov		PRETTY_CWS="${CWS} (at ${cnode})"
269144f180b8SYuri Pankov	fi
2692cdf0c1d5Smjnelsonelif [[ $SCM_MODE == "subversion" ]]; then
2693cdf0c1d5Smjnelson
2694cdf0c1d5Smjnelson	#
2695cdf0c1d5Smjnelson	# We only will have a real parent workspace in the case one
2696cdf0c1d5Smjnelson	# was specified (be it an older webrev, or another checkout).
2697cdf0c1d5Smjnelson	#
2698cdf0c1d5Smjnelson	[[ -n $codemgr_parent ]] && PWS=$codemgr_parent
2699cdf0c1d5Smjnelson
2700cdf0c1d5Smjnelson	if [[ -z $flist_done && $flist_mode == "auto" ]]; then
2701cdf0c1d5Smjnelson		flist_from_subversion $CWS $OLDPWD
2702cdf0c1d5Smjnelson	fi
2703cdf0c1d5Smjnelsonelse
2704b0efaad7SJoshua M. Clulow	if [[ $SCM_MODE == "unknown" ]]; then
2705b0efaad7SJoshua M. Clulow		print -u2 "    Unknown type of SCM in use"
2706b0efaad7SJoshua M. Clulow	else
2707b0efaad7SJoshua M. Clulow		print -u2 "    Unsupported SCM in use: $SCM_MODE"
2708b0efaad7SJoshua M. Clulow	fi
2709cdf0c1d5Smjnelson
2710b0efaad7SJoshua M. Clulow	env_from_flist
2711cdf0c1d5Smjnelson
2712b0efaad7SJoshua M. Clulow	if [[ -z $CODEMGR_WS ]]; then
2713b0efaad7SJoshua M. Clulow		print -u2 "SCM not detected/supported and " \
2714b0efaad7SJoshua M. Clulow		    "CODEMGR_WS not specified"
2715b0efaad7SJoshua M. Clulow		exit 1
2716b0efaad7SJoshua M. Clulow		fi
2717cdf0c1d5Smjnelson
2718b0efaad7SJoshua M. Clulow	if [[ -z $CODEMGR_PARENT ]]; then
2719b0efaad7SJoshua M. Clulow		print -u2 "SCM not detected/supported and " \
2720b0efaad7SJoshua M. Clulow		    "CODEMGR_PARENT not specified"
2721b0efaad7SJoshua M. Clulow		exit 1
2722b0efaad7SJoshua M. Clulow	fi
2723cdf0c1d5Smjnelson
2724b0efaad7SJoshua M. Clulow	CWS=$CODEMGR_WS
2725b0efaad7SJoshua M. Clulow	PWS=$CODEMGR_PARENT
2726daaffb31Sdpfi
27277c478bd9Sstevel@tonic-gate
2728daaffb31Sdp#
2729daaffb31Sdp# If the user didn't specify a -i option, check to see if there is a
2730daaffb31Sdp# webrev-info file in the workspace directory.
2731daaffb31Sdp#
2732daaffb31Sdpif [[ -z $iflag && -r "$CWS/webrev-info" ]]; then
2733daaffb31Sdp	iflag=1
2734daaffb31Sdp	INCLUDE_FILE="$CWS/webrev-info"
27357c478bd9Sstevel@tonic-gatefi
27367c478bd9Sstevel@tonic-gate
2737daaffb31Sdpif [[ -n $iflag ]]; then
2738daaffb31Sdp	if [[ ! -r $INCLUDE_FILE ]]; then
2739daaffb31Sdp		print -u2 "include file '$INCLUDE_FILE' does not exist or is" \
2740daaffb31Sdp		    "not readable."
2741daaffb31Sdp		exit 1
2742daaffb31Sdp	else
2743daaffb31Sdp		#
2744daaffb31Sdp		# $INCLUDE_FILE may be a relative path, and the script alters
2745daaffb31Sdp		# PWD, so we just stash a copy in /tmp.
2746daaffb31Sdp		#
2747daaffb31Sdp		cp $INCLUDE_FILE /tmp/$$.include
2748daaffb31Sdp	fi
27497c478bd9Sstevel@tonic-gatefi
27507c478bd9Sstevel@tonic-gate
27510fd2682eSMark J. Nelson# DO_EVERYTHING: break point
27520fd2682eSMark J. Nelsonif [[ -n $Nflag ]]; then
27530fd2682eSMark J. Nelson	break
27540fd2682eSMark J. Nelsonfi
27550fd2682eSMark J. Nelson
27560fd2682eSMark J. Nelsontypeset -A itsinfo
27570fd2682eSMark J. Nelsontypeset -r its_sed_script=/tmp/$$.its_sed
27580fd2682eSMark J. Nelsonvalid_prefixes=
27590fd2682eSMark J. Nelsonif [[ -z $nflag ]]; then
27608bcea973SRichard Lowe	DEFREGFILE="$(/bin/dirname "$(whence $0)")/../etc/its.reg"
27610fd2682eSMark J. Nelson	if [[ -n $Iflag ]]; then
27620fd2682eSMark J. Nelson		REGFILE=$ITSREG
27630fd2682eSMark J. Nelson	elif [[ -r $HOME/.its.reg ]]; then
27640fd2682eSMark J. Nelson		REGFILE=$HOME/.its.reg
27650fd2682eSMark J. Nelson	else
27660fd2682eSMark J. Nelson		REGFILE=$DEFREGFILE
27670fd2682eSMark J. Nelson	fi
27680fd2682eSMark J. Nelson	if [[ ! -r $REGFILE ]]; then
27690fd2682eSMark J. Nelson		print "ERROR: Unable to read database registry file $REGFILE"
27700fd2682eSMark J. Nelson		exit 1
27710fd2682eSMark J. Nelson	elif [[ $REGFILE != $DEFREGFILE ]]; then
27720fd2682eSMark J. Nelson		print "   its.reg from: $REGFILE"
27730fd2682eSMark J. Nelson	fi
27740fd2682eSMark J. Nelson
2775b1374179SBill Sommerfeld	$SED -e '/^#/d' -e $'/^[ \t]*$/d' $REGFILE | while read LINE; do
2776e6ccc173SEdward Pilatowicz
27770fd2682eSMark J. Nelson		name=${LINE%%=*}
27780fd2682eSMark J. Nelson		value="${LINE#*=}"
27790fd2682eSMark J. Nelson
27800fd2682eSMark J. Nelson		if [[ $name == PREFIX ]]; then
27810fd2682eSMark J. Nelson			p=${value}
27820fd2682eSMark J. Nelson			valid_prefixes="${p} ${valid_prefixes}"
27830fd2682eSMark J. Nelson		else
27840fd2682eSMark J. Nelson			itsinfo["${p}_${name}"]="${value}"
27850fd2682eSMark J. Nelson		fi
27860fd2682eSMark J. Nelson	done
27870fd2682eSMark J. Nelson
27880fd2682eSMark J. Nelson
27898bcea973SRichard Lowe	DEFCONFFILE="$(/bin/dirname "$(whence $0)")/../etc/its.conf"
27900fd2682eSMark J. Nelson	CONFFILES=$DEFCONFFILE
27910fd2682eSMark J. Nelson	if [[ -r $HOME/.its.conf ]]; then
27920fd2682eSMark J. Nelson		CONFFILES="${CONFFILES} $HOME/.its.conf"
27930fd2682eSMark J. Nelson	fi
27940fd2682eSMark J. Nelson	if [[ -n $Cflag ]]; then
27950fd2682eSMark J. Nelson		CONFFILES="${CONFFILES} ${ITSCONF}"
27960fd2682eSMark J. Nelson	fi
27970fd2682eSMark J. Nelson	its_domain=
27980fd2682eSMark J. Nelson	its_priority=
27990fd2682eSMark J. Nelson	for cf in ${CONFFILES}; do
28000fd2682eSMark J. Nelson		if [[ ! -r $cf ]]; then
28010fd2682eSMark J. Nelson			print "ERROR: Unable to read database configuration file $cf"
28020fd2682eSMark J. Nelson			exit 1
28030fd2682eSMark J. Nelson		elif [[ $cf != $DEFCONFFILE ]]; then
28040fd2682eSMark J. Nelson			print "       its.conf: reading $cf"
28050fd2682eSMark J. Nelson		fi
2806b1374179SBill Sommerfeld		$SED -e '/^#/d' -e $'/^[ \t]*$/d' $cf | while read LINE; do
28070fd2682eSMark J. Nelson		    eval "${LINE}"
28080fd2682eSMark J. Nelson		done
28090fd2682eSMark J. Nelson	done
28100fd2682eSMark J. Nelson
28110fd2682eSMark J. Nelson	#
28120fd2682eSMark J. Nelson	# If an information tracking system is explicitly identified by prefix,
28130fd2682eSMark J. Nelson	# we want to disregard the specified priorities and resolve it accordingly.
28140fd2682eSMark J. Nelson	#
28150fd2682eSMark J. Nelson	# To that end, we'll build a sed script to do each valid prefix in turn.
28160fd2682eSMark J. Nelson	#
28170fd2682eSMark J. Nelson	for p in ${valid_prefixes}; do
28180fd2682eSMark J. Nelson		#
28190fd2682eSMark J. Nelson		# When an informational URL was provided, translate it to a
28200fd2682eSMark J. Nelson		# hyperlink.  When omitted, simply use the prefix text.
28210fd2682eSMark J. Nelson		#
28220fd2682eSMark J. Nelson		if [[ -z ${itsinfo["${p}_INFO"]} ]]; then
28230fd2682eSMark J. Nelson			itsinfo["${p}_INFO"]=${p}
28240fd2682eSMark J. Nelson		else
28250fd2682eSMark J. Nelson			itsinfo["${p}_INFO"]="<a href=\\\"${itsinfo["${p}_INFO"]}\\\">${p}</a>"
28260fd2682eSMark J. Nelson		fi
28270fd2682eSMark J. Nelson
28280fd2682eSMark J. Nelson		#
28290fd2682eSMark J. Nelson		# Assume that, for this invocation of webrev, all references
28300fd2682eSMark J. Nelson		# to this information tracking system should resolve through
28310fd2682eSMark J. Nelson		# the same URL.
28320fd2682eSMark J. Nelson		#
28330fd2682eSMark J. Nelson		# If the caller specified -O, then always use EXTERNAL_URL.
28340fd2682eSMark J. Nelson		#
28350fd2682eSMark J. Nelson		# Otherwise, look in the list of domains for a matching
28360fd2682eSMark J. Nelson		# INTERNAL_URL.
28370fd2682eSMark J. Nelson		#
28380fd2682eSMark J. Nelson		[[ -z $Oflag ]] && for d in ${its_domain}; do
28390fd2682eSMark J. Nelson			if [[ -n ${itsinfo["${p}_INTERNAL_URL_${d}"]} ]]; then
28400fd2682eSMark J. Nelson				itsinfo["${p}_URL"]="${itsinfo[${p}_INTERNAL_URL_${d}]}"
28410fd2682eSMark J. Nelson				break
28420fd2682eSMark J. Nelson			fi
28430fd2682eSMark J. Nelson		done
28440fd2682eSMark J. Nelson		if [[ -z ${itsinfo["${p}_URL"]} ]]; then
28450fd2682eSMark J. Nelson			itsinfo["${p}_URL"]="${itsinfo[${p}_EXTERNAL_URL]}"
28460fd2682eSMark J. Nelson		fi
28470fd2682eSMark J. Nelson
28480fd2682eSMark J. Nelson		#
28490fd2682eSMark J. Nelson		# Turn the destination URL into a hyperlink
28500fd2682eSMark J. Nelson		#
28510fd2682eSMark J. Nelson		itsinfo["${p}_URL"]="<a href=\\\"${itsinfo[${p}_URL]}\\\">&</a>"
28520fd2682eSMark J. Nelson
28532f54b716SRichard Lowe		# The character class below contains a literal tab
2854b1374179SBill Sommerfeld		print "/^${p}[: \t]/ {
28550fd2682eSMark J. Nelson				s;${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g
28560fd2682eSMark J. Nelson				s;^${p};${itsinfo[${p}_INFO]};
28570fd2682eSMark J. Nelson			}" >> ${its_sed_script}
28580fd2682eSMark J. Nelson	done
28590fd2682eSMark J. Nelson
28600fd2682eSMark J. Nelson	#
28610fd2682eSMark J. Nelson	# The previous loop took care of explicit specification.  Now use
28620fd2682eSMark J. Nelson	# the configured priorities to attempt implicit translations.
28630fd2682eSMark J. Nelson	#
28640fd2682eSMark J. Nelson	for p in ${its_priority}; do
2865b1374179SBill Sommerfeld		print "/^${itsinfo[${p}_REGEX]}[ \t]/ {
28662f54b716SRichard Lowe				s;^${itsinfo[${p}_REGEX]};${itsinfo[${p}_URL]};g
28670fd2682eSMark J. Nelson			}" >> ${its_sed_script}
28680fd2682eSMark J. Nelson	done
28690fd2682eSMark J. Nelsonfi
28700fd2682eSMark J. Nelson
28710fd2682eSMark J. Nelson#
28720fd2682eSMark J. Nelson# Search for DO_EVERYTHING above for matching "for" statement
28730fd2682eSMark J. Nelson# and explanation of this terminator.
28740fd2682eSMark J. Nelson#
28750fd2682eSMark J. Nelsondone
28760fd2682eSMark J. Nelson
2877daaffb31Sdp#
2878daaffb31Sdp# Output directory.
2879daaffb31Sdp#
2880daaffb31SdpWDIR=${WDIR:-$CWS/webrev}
2881daaffb31Sdp
2882daaffb31Sdp#
288302d26c39SVladimir Kotal# Name of the webrev, derived from the workspace name or output directory;
288402d26c39SVladimir Kotal# in the future this could potentially be an option.
2885daaffb31Sdp#
288602d26c39SVladimir Kotalif [[ -n $oflag ]]; then
288702d26c39SVladimir Kotal	WNAME=${WDIR##*/}
288802d26c39SVladimir Kotalelse
288902d26c39SVladimir Kotal	WNAME=${CWS##*/}
289002d26c39SVladimir Kotalfi
289102d26c39SVladimir Kotal
2892ba44d8a2SVladimir Kotal# Make sure remote target is well formed for remote upload/delete.
2893ba44d8a2SVladimir Kotalif [[ -n $Dflag || -n $Uflag ]]; then
2894b0088928SVladimir Kotal	#
2895ba44d8a2SVladimir Kotal	# If remote target is not specified, build it from scratch using
2896ba44d8a2SVladimir Kotal	# the default values.
2897b0088928SVladimir Kotal	#
2898ba44d8a2SVladimir Kotal	if [[ -z $tflag ]]; then
2899ba44d8a2SVladimir Kotal		remote_target=${DEFAULT_REMOTE_HOST}:${WNAME}
2900ba44d8a2SVladimir Kotal	else
2901b0088928SVladimir Kotal		#
2902b0088928SVladimir Kotal		# Check upload target prefix first.
2903b0088928SVladimir Kotal		#
2904b0088928SVladimir Kotal		if [[ "${remote_target}" != ${rsync_prefix}* &&
2905b0088928SVladimir Kotal		    "${remote_target}" != ${ssh_prefix}* ]]; then
2906b0088928SVladimir Kotal			print "ERROR: invalid prefix of upload URI" \
2907b0088928SVladimir Kotal			    "($remote_target)"
2908b0088928SVladimir Kotal			exit 1
2909b0088928SVladimir Kotal		fi
2910b0088928SVladimir Kotal		#
2911ba44d8a2SVladimir Kotal		# If destination specification is not in the form of
2912ba44d8a2SVladimir Kotal		# host_spec:remote_dir then assume it is just remote hostname
2913ba44d8a2SVladimir Kotal		# and append a colon and destination directory formed from
2914ba44d8a2SVladimir Kotal		# local webrev directory name.
2915b0088928SVladimir Kotal		#
2916b0088928SVladimir Kotal		typeset target_no_prefix=${remote_target##*://}
2917b0088928SVladimir Kotal		if [[ ${target_no_prefix} == *:* ]]; then
2918ba44d8a2SVladimir Kotal			if [[ "${remote_target}" == *: ]]; then
2919b0088928SVladimir Kotal				remote_target=${remote_target}${WNAME}
2920b0088928SVladimir Kotal			fi
2921b0088928SVladimir Kotal		else
2922b0088928SVladimir Kotal			if [[ ${target_no_prefix} == */* ]]; then
2923b0088928SVladimir Kotal				print "ERROR: badly formed upload URI" \
2924b0088928SVladimir Kotal					"($remote_target)"
2925b0088928SVladimir Kotal				exit 1
2926ba44d8a2SVladimir Kotal			else
2927b0088928SVladimir Kotal				remote_target=${remote_target}:${WNAME}
2928ba44d8a2SVladimir Kotal			fi
2929ba44d8a2SVladimir Kotal		fi
2930ba44d8a2SVladimir Kotal	fi
2931b0088928SVladimir Kotal
2932b0088928SVladimir Kotal	#
2933b0088928SVladimir Kotal	# Strip trailing slash. Each upload method will deal with directory
2934b0088928SVladimir Kotal	# specification separately.
2935b0088928SVladimir Kotal	#
2936b0088928SVladimir Kotal	remote_target=${remote_target%/}
2937ba44d8a2SVladimir Kotalfi
2938ba44d8a2SVladimir Kotal
2939b0088928SVladimir Kotal#
2940ba44d8a2SVladimir Kotal# Option -D by itself (option -U not present) implies no webrev generation.
2941b0088928SVladimir Kotal#
2942ba44d8a2SVladimir Kotalif [[ -z $Uflag && -n $Dflag ]]; then
2943b0088928SVladimir Kotal	delete_webrev 1 1
294402d26c39SVladimir Kotal	exit $?
294502d26c39SVladimir Kotalfi
29467c478bd9Sstevel@tonic-gate
2947b0088928SVladimir Kotal#
2948ba44d8a2SVladimir Kotal# Do not generate the webrev, just upload it or delete it.
2949b0088928SVladimir Kotal#
2950ba44d8a2SVladimir Kotalif [[ -n $nflag ]]; then
2951ba44d8a2SVladimir Kotal	if [[ -n $Dflag ]]; then
2952b0088928SVladimir Kotal		delete_webrev 1 1
2953ba44d8a2SVladimir Kotal		(( $? == 0 )) || exit $?
2954ba44d8a2SVladimir Kotal	fi
2955ba44d8a2SVladimir Kotal	if [[ -n $Uflag ]]; then
2956ba44d8a2SVladimir Kotal		upload_webrev
2957ba44d8a2SVladimir Kotal		exit $?
2958ba44d8a2SVladimir Kotal	fi
2959ba44d8a2SVladimir Kotalfi
2960ba44d8a2SVladimir Kotal
2961e0e0293aSjmcpif [ "${WDIR%%/*}" ]; then
29627c478bd9Sstevel@tonic-gate	WDIR=$PWD/$WDIR
29637c478bd9Sstevel@tonic-gatefi
2964daaffb31Sdp
2965daaffb31Sdpif [[ ! -d $WDIR ]]; then
2966daaffb31Sdp	mkdir -p $WDIR
2967ba44d8a2SVladimir Kotal	(( $? != 0 )) && exit 1
2968daaffb31Sdpfi
2969daaffb31Sdp
2970daaffb31Sdp#
2971daaffb31Sdp# Summarize what we're going to do.
2972daaffb31Sdp#
29738bcea973SRichard Loweprint "      Workspace: ${PRETTY_CWS:-$CWS}"
2974daaffb31Sdpif [[ -n $parent_webrev ]]; then
2975daaffb31Sdp	print "Compare against: webrev at $parent_webrev"
2976daaffb31Sdpelse
29778bcea973SRichard Lowe	print "Compare against: ${PRETTY_PWS:-$PWS}"
29787c478bd9Sstevel@tonic-gatefi
29797c478bd9Sstevel@tonic-gate
2980daaffb31Sdp[[ -n $INCLUDE_FILE ]] && print "      Including: $INCLUDE_FILE"
2981daaffb31Sdpprint "      Output to: $WDIR"
2982daaffb31Sdp
2983daaffb31Sdp#
29847c478bd9Sstevel@tonic-gate# Save the file list in the webrev dir
2985daaffb31Sdp#
2986daaffb31Sdp[[ ! $FLIST -ef $WDIR/file.list ]] && cp $FLIST $WDIR/file.list
29877c478bd9Sstevel@tonic-gate
2988daaffb31Sdprm -f $WDIR/$WNAME.patch
29897c478bd9Sstevel@tonic-gate
2990daaffb31Sdptouch $WDIR/$WNAME.patch
29917c478bd9Sstevel@tonic-gate
2992daaffb31Sdpprint "   Output Files:"
29937c478bd9Sstevel@tonic-gate
2994daaffb31Sdp#
2995daaffb31Sdp# Clean up the file list: Remove comments, blank lines and env variables.
2996daaffb31Sdp#
2997b0088928SVladimir Kotal$SED -e "s/#.*$//" -e "/=/d" -e "/^[   ]*$/d" $FLIST > /tmp/$$.flist.clean
2998daaffb31SdpFLIST=/tmp/$$.flist.clean
2999daaffb31Sdp
3000daaffb31Sdp#
3001daaffb31Sdp# First pass through the files: generate the per-file webrev HTML-files.
3002daaffb31Sdp#
3003daaffb31Sdpcat $FLIST | while read LINE
30047c478bd9Sstevel@tonic-gatedo
3005b1374179SBill Sommerfeld	set -A FIELDS $LINE
3006b1374179SBill Sommerfeld	P=${FIELDS[0]}
30077c478bd9Sstevel@tonic-gate
3008daaffb31Sdp	#
3009daaffb31Sdp	# Normally, each line in the file list is just a pathname of a
3010daaffb31Sdp	# file that has been modified or created in the child.  A file
3011daaffb31Sdp	# that is renamed in the child workspace has two names on the
3012daaffb31Sdp	# line: new name followed by the old name.
3013daaffb31Sdp	#
3014daaffb31Sdp	oldname=""
3015daaffb31Sdp	oldpath=""
3016daaffb31Sdp	rename=
3017b1374179SBill Sommerfeld	if (( ${#FIELDS[*]} == 2 )); then
3018b1374179SBill Sommerfeld		PP=${FIELDS[1]}			# old filename
3019e6ccc173SEdward Pilatowicz		if [[ -f $PP ]]; then
3020e6ccc173SEdward Pilatowicz			oldname=" (copied from $PP)"
3021e6ccc173SEdward Pilatowicz		else
3022e6ccc173SEdward Pilatowicz			oldname=" (renamed from $PP)"
3023e6ccc173SEdward Pilatowicz		fi
3024daaffb31Sdp		oldpath="$PP"
3025daaffb31Sdp		rename=1
3026e6ccc173SEdward Pilatowicz		PDIR=${PP%/*}
3027e6ccc173SEdward Pilatowicz		if [[ $PDIR == $PP ]]; then
30287c478bd9Sstevel@tonic-gate			PDIR="."   # File at root of workspace
30297c478bd9Sstevel@tonic-gate		fi
30307c478bd9Sstevel@tonic-gate
30317c478bd9Sstevel@tonic-gate		PF=${PP##*/}
30327c478bd9Sstevel@tonic-gate
3033e6ccc173SEdward Pilatowicz		DIR=${P%/*}
3034e6ccc173SEdward Pilatowicz		if [[ $DIR == $P ]]; then
30357c478bd9Sstevel@tonic-gate			DIR="."   # File at root of workspace
30367c478bd9Sstevel@tonic-gate		fi
3037daaffb31Sdp
30387c478bd9Sstevel@tonic-gate		F=${P##*/}
3039daaffb31Sdp
3040b0efaad7SJoshua M. Clulow	else
3041e6ccc173SEdward Pilatowicz		DIR=${P%/*}
3042e6ccc173SEdward Pilatowicz		if [[ "$DIR" == "$P" ]]; then
30437c478bd9Sstevel@tonic-gate			DIR="."   # File at root of workspace
30447c478bd9Sstevel@tonic-gate		fi
3045daaffb31Sdp
30467c478bd9Sstevel@tonic-gate		F=${P##*/}
30477c478bd9Sstevel@tonic-gate
30487c478bd9Sstevel@tonic-gate		PP=$P
30497c478bd9Sstevel@tonic-gate		PDIR=$DIR
30507c478bd9Sstevel@tonic-gate		PF=$F
30517c478bd9Sstevel@tonic-gate	fi
30527c478bd9Sstevel@tonic-gate
3053b1374179SBill Sommerfeld	COMM=$(getcomments html $P $PP)
30547c478bd9Sstevel@tonic-gate
3055daaffb31Sdp	print "\t$P$oldname\n\t\t\c"
30567c478bd9Sstevel@tonic-gate
30577c478bd9Sstevel@tonic-gate	# Make the webrev mirror directory if necessary
3058daaffb31Sdp	mkdir -p $WDIR/$DIR
30597c478bd9Sstevel@tonic-gate
3060daaffb31Sdp	#
3061cdf0c1d5Smjnelson	# We stash old and new files into parallel directories in $WDIR
3062daaffb31Sdp	# and do our diffs there.  This makes it possible to generate
3063daaffb31Sdp	# clean looking diffs which don't have absolute paths present.
3064daaffb31Sdp	#
3065daaffb31Sdp
3066cdf0c1d5Smjnelson	build_old_new "$WDIR" "$PWS" "$PDIR" "$PF" "$CWS" "$DIR" "$F" || \
3067cdf0c1d5Smjnelson	    continue
30687c478bd9Sstevel@tonic-gate
3069cdf0c1d5Smjnelson	#
3070cdf0c1d5Smjnelson	# Keep the old PWD around, so we can safely switch back after
3071cdf0c1d5Smjnelson	# diff generation, such that build_old_new runs in a
3072cdf0c1d5Smjnelson	# consistent environment.
3073cdf0c1d5Smjnelson	#
3074cdf0c1d5Smjnelson	OWD=$PWD
3075daaffb31Sdp	cd $WDIR/raw_files
30763d7afa33SJoshua M. Clulow
30773d7afa33SJoshua M. Clulow	#
30783d7afa33SJoshua M. Clulow	# The "git apply" command does not tolerate the spurious
30793d7afa33SJoshua M. Clulow	# "./" that we otherwise insert; be careful not to include
30803d7afa33SJoshua M. Clulow	# it in the paths that we pass to diff(1).
30813d7afa33SJoshua M. Clulow	#
30823d7afa33SJoshua M. Clulow	if [[ $PDIR == "." ]]; then
30833d7afa33SJoshua M. Clulow		ofile=old/$PF
30843d7afa33SJoshua M. Clulow	else
30853d7afa33SJoshua M. Clulow		ofile=old/$PDIR/$PF
30863d7afa33SJoshua M. Clulow	fi
30873d7afa33SJoshua M. Clulow	if [[ $DIR == "." ]]; then
30883d7afa33SJoshua M. Clulow		nfile=new/$F
30893d7afa33SJoshua M. Clulow	else
30903d7afa33SJoshua M. Clulow		nfile=new/$DIR/$F
30913d7afa33SJoshua M. Clulow	fi
3092daaffb31Sdp
3093daaffb31Sdp	mv_but_nodiff=
3094daaffb31Sdp	cmp $ofile $nfile > /dev/null 2>&1
3095daaffb31Sdp	if [[ $? == 0 && $rename == 1 ]]; then
3096daaffb31Sdp		mv_but_nodiff=1
3097daaffb31Sdp	fi
3098daaffb31Sdp
3099daaffb31Sdp	#
3100daaffb31Sdp	# If we have old and new versions of the file then run the appropriate
3101daaffb31Sdp	# diffs.  This is complicated by a couple of factors:
3102daaffb31Sdp	#
3103daaffb31Sdp	#	- renames must be handled specially: we emit a 'remove'
3104daaffb31Sdp	#	  diff and an 'add' diff
3105daaffb31Sdp	#	- new files and deleted files must be handled specially
3106b0efaad7SJoshua M. Clulow	#	- GNU patch doesn't interpret the output of illumos diff
31077ffa1fbeSYuri Pankov	#	  properly when it comes to adds and deletes.  We need to
31087ffa1fbeSYuri Pankov	#	  do some "cleansing" transformations:
3109e6ccc173SEdward Pilatowicz	#	    [to add a file] @@ -1,0 +X,Y @@  -->  @@ -0,0 +X,Y @@
3110daaffb31Sdp	#	    [to del a file] @@ -X,Y +1,0 @@  -->  @@ -X,Y +0,0 @@
3111daaffb31Sdp	#
3112b0088928SVladimir Kotal	cleanse_rmfile="$SED 's/^\(@@ [0-9+,-]*\) [0-9+,-]* @@$/\1 +0,0 @@/'"
3113b0088928SVladimir Kotal	cleanse_newfile="$SED 's/^@@ [0-9+,-]* \([0-9+,-]* @@\)$/@@ -0,0 \1/'"
3114daaffb31Sdp
3115daaffb31Sdp	rm -f $WDIR/$DIR/$F.patch
3116daaffb31Sdp	if [[ -z $rename ]]; then
3117e0e0293aSjmcp		if [ ! -f "$ofile" ]; then
3118daaffb31Sdp			diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
3119daaffb31Sdp			    > $WDIR/$DIR/$F.patch
3120e0e0293aSjmcp		elif [ ! -f "$nfile" ]; then
3121daaffb31Sdp			diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
3122daaffb31Sdp			    > $WDIR/$DIR/$F.patch
3123daaffb31Sdp		else
3124daaffb31Sdp			diff -u $ofile $nfile > $WDIR/$DIR/$F.patch
3125daaffb31Sdp		fi
3126daaffb31Sdp	else
3127daaffb31Sdp		diff -u $ofile /dev/null | sh -c "$cleanse_rmfile" \
3128daaffb31Sdp		    > $WDIR/$DIR/$F.patch
3129daaffb31Sdp
3130daaffb31Sdp		diff -u /dev/null $nfile | sh -c "$cleanse_newfile" \
3131daaffb31Sdp		    >> $WDIR/$DIR/$F.patch
3132daaffb31Sdp	fi
3133daaffb31Sdp
3134daaffb31Sdp	#
3135daaffb31Sdp	# Tack the patch we just made onto the accumulated patch for the
3136daaffb31Sdp	# whole wad.
3137daaffb31Sdp	#
3138daaffb31Sdp	cat $WDIR/$DIR/$F.patch >> $WDIR/$WNAME.patch
3139daaffb31Sdp	print " patch\c"
31407c478bd9Sstevel@tonic-gate
3141daaffb31Sdp	if [[ -f $ofile && -f $nfile && -z $mv_but_nodiff ]]; then
3142daaffb31Sdp		${CDIFFCMD:-diff -bt -C 5} $ofile $nfile > $WDIR/$DIR/$F.cdiff
3143daaffb31Sdp		diff_to_html $F $DIR/$F "C" "$COMM" < $WDIR/$DIR/$F.cdiff \
3144daaffb31Sdp		    > $WDIR/$DIR/$F.cdiff.html
31457c478bd9Sstevel@tonic-gate		print " cdiffs\c"
31467c478bd9Sstevel@tonic-gate
3147daaffb31Sdp		${UDIFFCMD:-diff -bt -U 5} $ofile $nfile > $WDIR/$DIR/$F.udiff
3148daaffb31Sdp		diff_to_html $F $DIR/$F "U" "$COMM" < $WDIR/$DIR/$F.udiff \
3149daaffb31Sdp		    > $WDIR/$DIR/$F.udiff.html
31507c478bd9Sstevel@tonic-gate		print " udiffs\c"
31517c478bd9Sstevel@tonic-gate
31527c478bd9Sstevel@tonic-gate		if [[ -x $WDIFF ]]; then
3153daaffb31Sdp			$WDIFF -c "$COMM" \
3154daaffb31Sdp			    -t "$WNAME Wdiff $DIR/$F" $ofile $nfile > \
3155daaffb31Sdp			    $WDIR/$DIR/$F.wdiff.html 2>/dev/null
3156b1374179SBill Sommerfeld			if (( $? == 0 )); then
3157daaffb31Sdp				print " wdiffs\c"
3158daaffb31Sdp			else
3159daaffb31Sdp				print " wdiffs[fail]\c"
3160daaffb31Sdp			fi
31617c478bd9Sstevel@tonic-gate		fi
31627c478bd9Sstevel@tonic-gate
3163daaffb31Sdp		sdiff_to_html $ofile $nfile $F $DIR "$COMM" \
3164daaffb31Sdp		    > $WDIR/$DIR/$F.sdiff.html
31657c478bd9Sstevel@tonic-gate		print " sdiffs\c"
3166daaffb31Sdp		print " frames\c"
31677c478bd9Sstevel@tonic-gate
31687c478bd9Sstevel@tonic-gate		rm -f $WDIR/$DIR/$F.cdiff $WDIR/$DIR/$F.udiff
3169daaffb31Sdp		difflines $ofile $nfile > $WDIR/$DIR/$F.count
3170daaffb31Sdp	elif [[ -f $ofile && -f $nfile && -n $mv_but_nodiff ]]; then
3171daaffb31Sdp		# renamed file: may also have differences
3172daaffb31Sdp		difflines $ofile $nfile > $WDIR/$DIR/$F.count
3173daaffb31Sdp	elif [[ -f $nfile ]]; then
31747c478bd9Sstevel@tonic-gate		# new file: count added lines
3175daaffb31Sdp		difflines /dev/null $nfile > $WDIR/$DIR/$F.count
3176daaffb31Sdp	elif [[ -f $ofile ]]; then
31777c478bd9Sstevel@tonic-gate		# old file: count deleted lines
3178daaffb31Sdp		difflines $ofile /dev/null > $WDIR/$DIR/$F.count
3179daaffb31Sdp	fi
3180daaffb31Sdp
31817ffa1fbeSYuri Pankov	#
31827ffa1fbeSYuri Pankov	# Check if it's man page, and create plain text, html and raw (ascii)
31837ffa1fbeSYuri Pankov	# output for the new version, as well as diffs against old version.
31847ffa1fbeSYuri Pankov	#
3185b1374179SBill Sommerfeld	if [[ -f "$nfile" && "$nfile" == *.+([0-9])*([a-zA-Z]) && \
31867ffa1fbeSYuri Pankov	    -x $MANDOC && -x $COL ]]; then
318783885279SYuri Pankov		$MANDOC -Tascii $nfile | $COL -b > $nfile.man.txt
31887ffa1fbeSYuri Pankov		source_to_html txt < $nfile.man.txt > $nfile.man.txt.html
31897ffa1fbeSYuri Pankov		print " man-txt\c"
31907ffa1fbeSYuri Pankov		print "$MANCSS" > $WDIR/raw_files/new/$DIR/man.css
31917ffa1fbeSYuri Pankov		$MANDOC -Thtml -Ostyle=man.css $nfile > $nfile.man.html
31927ffa1fbeSYuri Pankov		print " man-html\c"
31937ffa1fbeSYuri Pankov		$MANDOC -Tascii $nfile > $nfile.man.raw
31947ffa1fbeSYuri Pankov		print " man-raw\c"
31957ffa1fbeSYuri Pankov		if [[ -f "$ofile" && -z $mv_but_nodiff ]]; then
319683885279SYuri Pankov			$MANDOC -Tascii $ofile | $COL -b > $ofile.man.txt
31977ffa1fbeSYuri Pankov			${CDIFFCMD:-diff -bt -C 5} $ofile.man.txt \
31987ffa1fbeSYuri Pankov			    $nfile.man.txt > $WDIR/$DIR/$F.man.cdiff
31997ffa1fbeSYuri Pankov			diff_to_html $F $DIR/$F "C" "$COMM" < \
32007ffa1fbeSYuri Pankov			    $WDIR/$DIR/$F.man.cdiff > \
32017ffa1fbeSYuri Pankov			    $WDIR/$DIR/$F.man.cdiff.html
32027ffa1fbeSYuri Pankov			print " man-cdiffs\c"
32037ffa1fbeSYuri Pankov			${UDIFFCMD:-diff -bt -U 5} $ofile.man.txt \
32047ffa1fbeSYuri Pankov			    $nfile.man.txt > $WDIR/$DIR/$F.man.udiff
32057ffa1fbeSYuri Pankov			diff_to_html $F $DIR/$F "U" "$COMM" < \
32067ffa1fbeSYuri Pankov			    $WDIR/$DIR/$F.man.udiff > \
32077ffa1fbeSYuri Pankov			    $WDIR/$DIR/$F.man.udiff.html
32087ffa1fbeSYuri Pankov			print " man-udiffs\c"
32097ffa1fbeSYuri Pankov			if [[ -x $WDIFF ]]; then
32107ffa1fbeSYuri Pankov				$WDIFF -c "$COMM" -t "$WNAME Wdiff $DIR/$F" \
32117ffa1fbeSYuri Pankov				    $ofile.man.txt $nfile.man.txt > \
32127ffa1fbeSYuri Pankov				    $WDIR/$DIR/$F.man.wdiff.html 2>/dev/null
3213b1374179SBill Sommerfeld				if (( $? == 0 )); then
32147ffa1fbeSYuri Pankov					print " man-wdiffs\c"
32157ffa1fbeSYuri Pankov				else
32167ffa1fbeSYuri Pankov					print " man-wdiffs[fail]\c"
32177ffa1fbeSYuri Pankov				fi
32187ffa1fbeSYuri Pankov			fi
32197ffa1fbeSYuri Pankov			sdiff_to_html $ofile.man.txt $nfile.man.txt $F.man $DIR \
32207ffa1fbeSYuri Pankov			    "$COMM" > $WDIR/$DIR/$F.man.sdiff.html
32217ffa1fbeSYuri Pankov			print " man-sdiffs\c"
32227ffa1fbeSYuri Pankov			print " man-frames\c"
32237ffa1fbeSYuri Pankov		fi
32247ffa1fbeSYuri Pankov		rm -f $ofile.man.txt $nfile.man.txt
32257ffa1fbeSYuri Pankov		rm -f $WDIR/$DIR/$F.man.cdiff $WDIR/$DIR/$F.man.udiff
32267ffa1fbeSYuri Pankov	fi
32277ffa1fbeSYuri Pankov
3228cdf0c1d5Smjnelson	if [[ -f $ofile ]]; then
3229cdf0c1d5Smjnelson		source_to_html Old $PP < $ofile > $WDIR/$DIR/$F-.html
32307c478bd9Sstevel@tonic-gate		print " old\c"
32317c478bd9Sstevel@tonic-gate	fi
32327c478bd9Sstevel@tonic-gate
3233daaffb31Sdp	if [[ -f $nfile ]]; then
3234daaffb31Sdp		source_to_html New $P < $nfile > $WDIR/$DIR/$F.html
32357c478bd9Sstevel@tonic-gate		print " new\c"
32367c478bd9Sstevel@tonic-gate	fi
32377c478bd9Sstevel@tonic-gate
3238cdf0c1d5Smjnelson	cd $OWD
3239cdf0c1d5Smjnelson
3240daaffb31Sdp	print
32417c478bd9Sstevel@tonic-gatedone
32427c478bd9Sstevel@tonic-gate
3243daaffb31Sdpframe_nav_js > $WDIR/ancnav.js
3244daaffb31Sdpframe_navigation > $WDIR/ancnav.html
3245daaffb31Sdp
3246e0e0293aSjmcp# If we're in OpenSolaris mode and there's a closed dir under $WDIR,
3247e0e0293aSjmcp# delete it - prevent accidental publishing of closed source
3248e0e0293aSjmcp
3249e0e0293aSjmcpif [[ -n "$Oflag" ]]; then
3250ba44d8a2SVladimir Kotal	$FIND $WDIR -type d -name closed -exec /bin/rm -rf {} \;
3251e0e0293aSjmcpfi
3252e0e0293aSjmcp
32537c478bd9Sstevel@tonic-gate# Now build the index.html file that contains
32547c478bd9Sstevel@tonic-gate# links to the source files and their diffs.
32557c478bd9Sstevel@tonic-gate
32567c478bd9Sstevel@tonic-gatecd $CWS
32577c478bd9Sstevel@tonic-gate
32587c478bd9Sstevel@tonic-gate# Save total changed lines for Code Inspection.
3259daaffb31Sdpprint "$TOTL" > $WDIR/TotalChangedLines
32607c478bd9Sstevel@tonic-gate
3261daaffb31Sdpprint "     index.html: \c"
32627c478bd9Sstevel@tonic-gateINDEXFILE=$WDIR/index.html
32637c478bd9Sstevel@tonic-gateexec 3<&1			# duplicate stdout to FD3.
32647c478bd9Sstevel@tonic-gateexec 1<&-			# Close stdout.
32657c478bd9Sstevel@tonic-gateexec > $INDEXFILE		# Open stdout to index file.
32667c478bd9Sstevel@tonic-gate
3267daaffb31Sdpprint "$HTML<head>$STDHEAD"
3268daaffb31Sdpprint "<title>$WNAME</title>"
3269daaffb31Sdpprint "</head>"
3270daaffb31Sdpprint "<body id=\"SUNWwebrev\">"
3271daaffb31Sdpprint "<div class=\"summary\">"
3272daaffb31Sdpprint "<h2>Code Review for $WNAME</h2>"
3273daaffb31Sdp
3274daaffb31Sdpprint "<table>"
32757c478bd9Sstevel@tonic-gate
3276daaffb31Sdp#
3277cdf0c1d5Smjnelson# Get the preparer's name:
3278daaffb31Sdp#
32790f554fe5SRichard Lowe# If the SCM detected is Git, and the configuration property user.name is
32800f554fe5SRichard Lowe# available, use that, but be careful to properly escape angle brackets (HTML
32810f554fe5SRichard Lowe# syntax characters) in the email address.
3282cdf0c1d5Smjnelson#
3283cdf0c1d5Smjnelson# Otherwise, use the current userid in the form "John Doe (jdoe)", but
3284bbf21555SRichard Lowe# to maintain compatibility with passwd(5), we must support '&' substitutions.
3285cdf0c1d5Smjnelson#
3286cdf0c1d5Smjnelsonpreparer=
32870f554fe5SRichard Loweif [[ "$SCM_MODE" == git ]]; then
32880f554fe5SRichard Lowe	preparer=$(git config user.name 2>/dev/null)
3289cdf0c1d5Smjnelson	if [[ -n "$preparer" ]]; then
3290cdf0c1d5Smjnelson		preparer="$(echo "$preparer" | html_quote)"
3291cdf0c1d5Smjnelson	fi
3292cdf0c1d5Smjnelsonfi
3293cdf0c1d5Smjnelsonif [[ -z "$preparer" ]]; then
3294cdf0c1d5Smjnelson	preparer=$(
3295cdf0c1d5Smjnelson	    $PERL -e '
3296cdf0c1d5Smjnelson	        ($login, $pw, $uid, $gid, $quota, $cmt, $gcos) = getpwuid($<);
3297cdf0c1d5Smjnelson	        if ($login) {
3298cdf0c1d5Smjnelson	            $gcos =~ s/\&/ucfirst($login)/e;
3299cdf0c1d5Smjnelson	            printf "%s (%s)\n", $gcos, $login;
3300cdf0c1d5Smjnelson	        } else {
3301cdf0c1d5Smjnelson	            printf "(unknown)\n";
3302cdf0c1d5Smjnelson	        }
3303cdf0c1d5Smjnelson	')
3304daaffb31Sdpfi
3305daaffb31Sdp
330648bc00d6SjmcpPREPDATE=$(LC_ALL=C /usr/bin/date +%Y-%b-%d\ %R\ %z\ %Z)
330748bc00d6Sjmcpprint "<tr><th>Prepared by:</th><td>$preparer on $PREPDATE</td></tr>"
33088bcea973SRichard Loweprint "<tr><th>Workspace:</th><td>${PRETTY_CWS:-$CWS}"
3309cdf0c1d5Smjnelsonprint "</td></tr>"
3310daaffb31Sdpprint "<tr><th>Compare against:</th><td>"
3311daaffb31Sdpif [[ -n $parent_webrev ]]; then
3312daaffb31Sdp	print "webrev at $parent_webrev"
3313daaffb31Sdpelse
33148bcea973SRichard Lowe	print "${PRETTY_PWS:-$PWS}"
3315daaffb31Sdpfi
3316daaffb31Sdpprint "</td></tr>"
3317daaffb31Sdpprint "<tr><th>Summary of changes:</th><td>"
3318daaffb31SdpprintCI $TOTL $TINS $TDEL $TMOD $TUNC
3319daaffb31Sdpprint "</td></tr>"
3320daaffb31Sdp
3321daaffb31Sdpif [[ -f $WDIR/$WNAME.patch ]]; then
3322371d72daSLubomir Sedlacik	wpatch_url="$(print $WNAME.patch | url_encode)"
3323daaffb31Sdp	print "<tr><th>Patch of changes:</th><td>"
3324371d72daSLubomir Sedlacik	print "<a href=\"$wpatch_url\">$WNAME.patch</a></td></tr>"
3325daaffb31Sdpfi
33267c478bd9Sstevel@tonic-gate
3327daaffb31Sdpif [[ -n "$iflag" ]]; then
3328daaffb31Sdp	print "<tr><th>Author comments:</th><td><div>"
3329daaffb31Sdp	cat /tmp/$$.include
3330daaffb31Sdp	print "</div></td></tr>"
3331daaffb31Sdpfi
3332daaffb31Sdpprint "</table>"
3333daaffb31Sdpprint "</div>"
3334daaffb31Sdp
3335daaffb31Sdp#
3336daaffb31Sdp# Second pass through the files: generate the rest of the index file
3337daaffb31Sdp#
3338daaffb31Sdpcat $FLIST | while read LINE
33397c478bd9Sstevel@tonic-gatedo
3340b1374179SBill Sommerfeld	set -A FIELDS $LINE
3341b1374179SBill Sommerfeld	P=${FIELDS[0]}
33427c478bd9Sstevel@tonic-gate
3343b1374179SBill Sommerfeld	if (( ${#FIELDS[*]} == 2 )); then
3344b1374179SBill Sommerfeld		PP=${FIELDS[1]}
3345cdf0c1d5Smjnelson		oldname="$PP"
33467c478bd9Sstevel@tonic-gate	else
33477c478bd9Sstevel@tonic-gate		PP=$P
3348daaffb31Sdp		oldname=""
3349daaffb31Sdp	fi
3350daaffb31Sdp
3351cdf0c1d5Smjnelson	mv_but_nodiff=
3352cdf0c1d5Smjnelson	cmp $WDIR/raw_files/old/$PP $WDIR/raw_files/new/$P > /dev/null 2>&1
3353b1374179SBill Sommerfeld	if (( $? == 0 )) && [[ -n "$oldname" ]]; then
3354cdf0c1d5Smjnelson		mv_but_nodiff=1
3355cdf0c1d5Smjnelson	fi
3356cdf0c1d5Smjnelson
3357daaffb31Sdp	DIR=${P%/*}
3358daaffb31Sdp	if [[ $DIR == $P ]]; then
3359daaffb31Sdp		DIR="."   # File at root of workspace
33607c478bd9Sstevel@tonic-gate	fi
33617c478bd9Sstevel@tonic-gate
33627c478bd9Sstevel@tonic-gate	# Avoid processing the same file twice.
33637c478bd9Sstevel@tonic-gate	# It's possible for renamed files to
33647c478bd9Sstevel@tonic-gate	# appear twice in the file list
33657c478bd9Sstevel@tonic-gate
33667c478bd9Sstevel@tonic-gate	F=$WDIR/$P
33677c478bd9Sstevel@tonic-gate
3368daaffb31Sdp	print "<p>"
33697c478bd9Sstevel@tonic-gate
33707c478bd9Sstevel@tonic-gate	# If there's a diffs file, make diffs links
33717c478bd9Sstevel@tonic-gate
3372daaffb31Sdp	if [[ -f $F.cdiff.html ]]; then
3373371d72daSLubomir Sedlacik		cdiff_url="$(print $P.cdiff.html | url_encode)"
3374371d72daSLubomir Sedlacik		udiff_url="$(print $P.udiff.html | url_encode)"
33757ffa1fbeSYuri Pankov		sdiff_url="$(print $P.sdiff.html | url_encode)"
33767ffa1fbeSYuri Pankov		frames_url="$(print $P.frames.html | url_encode)"
3377371d72daSLubomir Sedlacik		print "<a href=\"$cdiff_url\">Cdiffs</a>"
3378371d72daSLubomir Sedlacik		print "<a href=\"$udiff_url\">Udiffs</a>"
3379daaffb31Sdp		if [[ -f $F.wdiff.html && -x $WDIFF ]]; then
3380371d72daSLubomir Sedlacik			wdiff_url="$(print $P.wdiff.html | url_encode)"
3381371d72daSLubomir Sedlacik			print "<a href=\"$wdiff_url\">Wdiffs</a>"
33827c478bd9Sstevel@tonic-gate		fi
3383371d72daSLubomir Sedlacik		print "<a href=\"$sdiff_url\">Sdiffs</a>"
3384371d72daSLubomir Sedlacik		print "<a href=\"$frames_url\">Frames</a>"
33857c478bd9Sstevel@tonic-gate	else
33867ffa1fbeSYuri Pankov		print " ------ ------"
3387daaffb31Sdp		if [[ -x $WDIFF ]]; then
33887c478bd9Sstevel@tonic-gate			print " ------"
33897c478bd9Sstevel@tonic-gate		fi
33907ffa1fbeSYuri Pankov		print " ------ ------"
33917c478bd9Sstevel@tonic-gate	fi
3392daaffb31Sdp
33937c478bd9Sstevel@tonic-gate	# If there's an old file, make the link
33947c478bd9Sstevel@tonic-gate
3395daaffb31Sdp	if [[ -f $F-.html ]]; then
3396371d72daSLubomir Sedlacik		oldfile_url="$(print $P-.html | url_encode)"
3397371d72daSLubomir Sedlacik		print "<a href=\"$oldfile_url\">Old</a>"
33987c478bd9Sstevel@tonic-gate	else
3399daaffb31Sdp		print " ---"
34007c478bd9Sstevel@tonic-gate	fi
3401daaffb31Sdp
34027c478bd9Sstevel@tonic-gate	# If there's an new file, make the link
34037c478bd9Sstevel@tonic-gate
3404daaffb31Sdp	if [[ -f $F.html ]]; then
3405371d72daSLubomir Sedlacik		newfile_url="$(print $P.html | url_encode)"
3406371d72daSLubomir Sedlacik		print "<a href=\"$newfile_url\">New</a>"
34077c478bd9Sstevel@tonic-gate	else
3408daaffb31Sdp		print " ---"
34097c478bd9Sstevel@tonic-gate	fi
34107c478bd9Sstevel@tonic-gate
3411daaffb31Sdp	if [[ -f $F.patch ]]; then
3412371d72daSLubomir Sedlacik		patch_url="$(print $P.patch | url_encode)"
3413371d72daSLubomir Sedlacik		print "<a href=\"$patch_url\">Patch</a>"
3414daaffb31Sdp	else
3415daaffb31Sdp		print " -----"
3416daaffb31Sdp	fi
34177c478bd9Sstevel@tonic-gate
3418daaffb31Sdp	if [[ -f $WDIR/raw_files/new/$P ]]; then
3419371d72daSLubomir Sedlacik		rawfiles_url="$(print raw_files/new/$P | url_encode)"
3420371d72daSLubomir Sedlacik		print "<a href=\"$rawfiles_url\">Raw</a>"
34217c478bd9Sstevel@tonic-gate	else
3422daaffb31Sdp		print " ---"
3423daaffb31Sdp	fi
3424daaffb31Sdp
3425cdf0c1d5Smjnelson	print "<b>$P</b>"
3426cdf0c1d5Smjnelson
3427cdf0c1d5Smjnelson	# For renamed files, clearly state whether or not they are modified
3428e6ccc173SEdward Pilatowicz	if [[ -f "$oldname" ]]; then
3429e6ccc173SEdward Pilatowicz		if [[ -n "$mv_but_nodiff" ]]; then
3430e6ccc173SEdward Pilatowicz			print "<i>(copied from $oldname)</i>"
3431e6ccc173SEdward Pilatowicz		else
3432e6ccc173SEdward Pilatowicz			print "<i>(copied and modified from $oldname)</i>"
3433e6ccc173SEdward Pilatowicz		fi
3434e6ccc173SEdward Pilatowicz	elif [[ -n "$oldname" ]]; then
3435cdf0c1d5Smjnelson		if [[ -n "$mv_but_nodiff" ]]; then
3436e6ccc173SEdward Pilatowicz			print "<i>(renamed from $oldname)</i>"
3437cdf0c1d5Smjnelson		else
3438e6ccc173SEdward Pilatowicz			print "<i>(renamed and modified from $oldname)</i>"
3439cdf0c1d5Smjnelson		fi
3440cdf0c1d5Smjnelson	fi
3441cdf0c1d5Smjnelson
3442cdf0c1d5Smjnelson	# If there's an old file, but no new file, the file was deleted
3443cdf0c1d5Smjnelson	if [[ -f $F-.html && ! -f $F.html ]]; then
3444cdf0c1d5Smjnelson		print " <i>(deleted)</i>"
3445cdf0c1d5Smjnelson	fi
3446daaffb31Sdp
3447e0e0293aSjmcp	# Check for usr/closed and deleted_files/usr/closed
3448daaffb31Sdp	if [ ! -z "$Oflag" ]; then
3449e0e0293aSjmcp		if [[ $P == usr/closed/* || \
3450e0e0293aSjmcp		    $P == deleted_files/usr/closed/* ]]; then
3451daaffb31Sdp			print "&nbsp;&nbsp;<i>Closed source: omitted from" \
3452daaffb31Sdp			    "this review</i>"
3453daaffb31Sdp		fi
34547c478bd9Sstevel@tonic-gate	fi
34557c478bd9Sstevel@tonic-gate
34567ffa1fbeSYuri Pankov	manpage=
34577ffa1fbeSYuri Pankov	if [[ -f $F.man.cdiff.html || \
34587ffa1fbeSYuri Pankov	    -f $WDIR/raw_files/new/$P.man.txt.html ]]; then
34597ffa1fbeSYuri Pankov		manpage=1
34607ffa1fbeSYuri Pankov		print "<br/>man:"
34617ffa1fbeSYuri Pankov	fi
34627ffa1fbeSYuri Pankov
34637ffa1fbeSYuri Pankov	if [[ -f $F.man.cdiff.html ]]; then
34647ffa1fbeSYuri Pankov		mancdiff_url="$(print $P.man.cdiff.html | url_encode)"
34657ffa1fbeSYuri Pankov		manudiff_url="$(print $P.man.udiff.html | url_encode)"
34667ffa1fbeSYuri Pankov		mansdiff_url="$(print $P.man.sdiff.html | url_encode)"
34677ffa1fbeSYuri Pankov		manframes_url="$(print $P.man.frames.html | url_encode)"
34687ffa1fbeSYuri Pankov		print "<a href=\"$mancdiff_url\">Cdiffs</a>"
34697ffa1fbeSYuri Pankov		print "<a href=\"$manudiff_url\">Udiffs</a>"
34707ffa1fbeSYuri Pankov		if [[ -f $F.man.wdiff.html && -x $WDIFF ]]; then
34717ffa1fbeSYuri Pankov			manwdiff_url="$(print $P.man.wdiff.html | url_encode)"
34727ffa1fbeSYuri Pankov			print "<a href=\"$manwdiff_url\">Wdiffs</a>"
34737ffa1fbeSYuri Pankov		fi
34747ffa1fbeSYuri Pankov		print "<a href=\"$mansdiff_url\">Sdiffs</a>"
34757ffa1fbeSYuri Pankov		print "<a href=\"$manframes_url\">Frames</a>"
34767ffa1fbeSYuri Pankov	elif [[ -n $manpage ]]; then
34777ffa1fbeSYuri Pankov		print " ------ ------"
34787ffa1fbeSYuri Pankov		if [[ -x $WDIFF ]]; then
34797ffa1fbeSYuri Pankov			print " ------"
34807ffa1fbeSYuri Pankov		fi
34817ffa1fbeSYuri Pankov		print " ------ ------"
34827ffa1fbeSYuri Pankov	fi
34837ffa1fbeSYuri Pankov
34847ffa1fbeSYuri Pankov	if [[ -f $WDIR/raw_files/new/$P.man.txt.html ]]; then
34857ffa1fbeSYuri Pankov		mantxt_url="$(print raw_files/new/$P.man.txt.html | url_encode)"
34867ffa1fbeSYuri Pankov		print "<a href=\"$mantxt_url\">TXT</a>"
34877ffa1fbeSYuri Pankov		manhtml_url="$(print raw_files/new/$P.man.html | url_encode)"
34887ffa1fbeSYuri Pankov		print "<a href=\"$manhtml_url\">HTML</a>"
34897ffa1fbeSYuri Pankov		manraw_url="$(print raw_files/new/$P.man.raw | url_encode)"
34907ffa1fbeSYuri Pankov		print "<a href=\"$manraw_url\">Raw</a>"
34917ffa1fbeSYuri Pankov	elif [[ -n $manpage ]]; then
34927ffa1fbeSYuri Pankov		print " --- ---- ---"
34937ffa1fbeSYuri Pankov	fi
34947ffa1fbeSYuri Pankov
3495daaffb31Sdp	print "</p>"
3496daaffb31Sdp
34977ffa1fbeSYuri Pankov	# Insert delta comments
3498daaffb31Sdp	print "<blockquote><pre>"
3499daaffb31Sdp	getcomments html $P $PP
3500daaffb31Sdp	print "</pre>"
3501daaffb31Sdp
35027c478bd9Sstevel@tonic-gate	# Add additional comments comment
3503daaffb31Sdp	print "<!-- Add comments to explain changes in $P here -->"
35047c478bd9Sstevel@tonic-gate
35057c478bd9Sstevel@tonic-gate	# Add count of changes.
3506daaffb31Sdp	if [[ -f $F.count ]]; then
35077c478bd9Sstevel@tonic-gate	    cat $F.count
35087c478bd9Sstevel@tonic-gate	    rm $F.count
35097c478bd9Sstevel@tonic-gate	fi
3510cdf0c1d5Smjnelson
35110f554fe5SRichard Lowe	if [[ $SCM_MODE == "unknown" ]]; then
3512cdf0c1d5Smjnelson		# Include warnings for important file mode situations:
3513cdf0c1d5Smjnelson		# 1) New executable files
3514cdf0c1d5Smjnelson		# 2) Permission changes of any kind
3515cdf0c1d5Smjnelson		# 3) Existing executable files
3516cdf0c1d5Smjnelson		old_mode=
3517cdf0c1d5Smjnelson		if [[ -f $WDIR/raw_files/old/$PP ]]; then
3518b1374179SBill Sommerfeld			old_mode=$(get_file_mode $WDIR/raw_files/old/$PP)
3519cdf0c1d5Smjnelson		fi
3520cdf0c1d5Smjnelson
3521cdf0c1d5Smjnelson		new_mode=
3522cdf0c1d5Smjnelson		if [[ -f $WDIR/raw_files/new/$P ]]; then
3523b1374179SBill Sommerfeld			new_mode=$(get_file_mode $WDIR/raw_files/new/$P)
3524cdf0c1d5Smjnelson		fi
3525cdf0c1d5Smjnelson
3526b1374179SBill Sommerfeld		if [[ -z "$old_mode" && "$new_mode" == *[1357]* ]]; then
3527cdf0c1d5Smjnelson			print "<span class=\"chmod\">"
3528cdf0c1d5Smjnelson			print "<p>new executable file: mode $new_mode</p>"
3529cdf0c1d5Smjnelson			print "</span>"
3530cdf0c1d5Smjnelson		elif [[ -n "$old_mode" && -n "$new_mode" &&
3531cdf0c1d5Smjnelson		    "$old_mode" != "$new_mode" ]]; then
3532cdf0c1d5Smjnelson			print "<span class=\"chmod\">"
3533cdf0c1d5Smjnelson			print "<p>mode change: $old_mode to $new_mode</p>"
3534cdf0c1d5Smjnelson			print "</span>"
3535b1374179SBill Sommerfeld		elif [[ "$new_mode" == *[1357]* ]]; then
3536cdf0c1d5Smjnelson			print "<span class=\"chmod\">"
3537cdf0c1d5Smjnelson			print "<p>executable file: mode $new_mode</p>"
3538cdf0c1d5Smjnelson			print "</span>"
3539cdf0c1d5Smjnelson		fi
3540cdf0c1d5Smjnelson	fi
3541cdf0c1d5Smjnelson
3542daaffb31Sdp	print "</blockquote>"
35437c478bd9Sstevel@tonic-gatedone
35447c478bd9Sstevel@tonic-gate
3545daaffb31Sdpprint
3546daaffb31Sdpprint
3547cac38512Smjnelsonprint "<hr></hr>"
3548daaffb31Sdpprint "<p style=\"font-size: small\">"
35499a70fc3bSMark J. Nelsonprint "This code review page was prepared using <b>$0</b>."
355087a4464eSChris Loveprint "Webrev is maintained by the <a href=\"http://www.illumos.org\">"
355187a4464eSChris Loveprint "illumos</a> project.  The latest version may be obtained"
35527646c8f3SMarcel Telkaprint "<a href=\"http://src.illumos.org/source/xref/illumos-gate/usr/src/tools/scripts/webrev.sh\">here</a>.</p>"
3553daaffb31Sdpprint "</body>"
3554daaffb31Sdpprint "</html>"
35557c478bd9Sstevel@tonic-gate
35567c478bd9Sstevel@tonic-gateexec 1<&-			# Close FD 1.
35577c478bd9Sstevel@tonic-gateexec 1<&3			# dup FD 3 to restore stdout.
35587c478bd9Sstevel@tonic-gateexec 3<&-			# close FD 3.
35597c478bd9Sstevel@tonic-gate
3560daaffb31Sdpprint "Done."
356102d26c39SVladimir Kotal
3562b0088928SVladimir Kotal#
3563ba44d8a2SVladimir Kotal# If remote deletion was specified and fails do not continue.
3564b0088928SVladimir Kotal#
3565ba44d8a2SVladimir Kotalif [[ -n $Dflag ]]; then
3566b0088928SVladimir Kotal	delete_webrev 1 1
3567ba44d8a2SVladimir Kotal	(( $? == 0 )) || exit $?
3568ba44d8a2SVladimir Kotalfi
3569ba44d8a2SVladimir Kotal
357002d26c39SVladimir Kotalif [[ -n $Uflag ]]; then
357102d26c39SVladimir Kotal	upload_webrev
357202d26c39SVladimir Kotal	exit $?
357302d26c39SVladimir Kotalfi
3574