- #!/usr/bin/perl
-
- # $Id: //depot/cad/tools/1.0/icp4-1.1/bin/p4ci#31 $
- #
- # CSWITCH CORPORATION CONFIDENTIAL PROPRIETARY
- #
- # This file contains information which is the
- # proprietary property of Cswitch Corporation.
- # This file is confidential and its contents may
- # not be disclosed without the expressed written
- # consent of Cswitch Corporation.
-
-
- # For each cell given:
- # error check
- # make list of cells to add/submit
- # bring up edit page
- # Do together:
- # revert -a
- # add
- # submit
-
- use strict;
- use warnings;
-
- use FindBin qw($Bin);
- use lib "$Bin/../lib";
-
- use Icp4;
- use Getopt::Std;
- use File::Basename;
- use Cwd;
-
- our ($Program, %opt, $islayout, $nflag, $rflag, $client, $cells, $support);
-
- our $attr_sfx = ".Ic_cell_template.attr";
- our $cell_sfx = ".iccel_[0-9]+";
-
- our $keep = 1;
-
- # each file in raw_list has a file status:
- # raw
- # edit
- # add
- # revert
- our %file_status;
- our @raw_list;
-
- our @revert_list;
- our @add_list;
- our @edit_list;
-
- our @user_add_list;
- our @user_edit_list;
-
- # turn on logging of p4ci to ~/p4ci.log
- my $P4CI_LOG = 1;
- #my $P4CI_LOG = 0;
-
-
- MAIN: {
-
- $Program = $FindBin::Script;
-
- getopts('hDnirk:', \%opt);
-
- if ($opt{h} || $#ARGV < 0) {
- print "Usage: $Program [-h] [-n] [-i] [-k num] [-r] cell+\n";
- print " -h: help usage\n";
- print " -n: show operation only\n";
- print " -i: ignore pending changes (dangerous!)\n";
- print " -k: number of versions to keep\n";
- print " (default: $keep, works for layout only for now)\n";
- print " -r: remain open for edit after checkin\n";
- print " (default: locked after checkin)\n";
- print " cell: cell name(s)\n";
- print " (hint: use \\\$ for cells with \$ character in their name)\n";
- exit 0;
- }
-
- $nflag = ($opt{n}) ? "-n" : "" ;
- $rflag = ($opt{r}) ? "-r" : "" ;
- $keep = $opt{k} if ($opt{k});
-
- #$Icp4::debug = ($opt{D}) ? 1 : 0 ;
- # keep Icp4 quiet
- $Icp4::debug = 0;
- $Icp4::nflag = ($opt{n}) ? 1 : 0 ;
-
- # make sure p4 is configured
- if (&Icp4::where() eq 'error') {
- print "ERROR: Current directory not in client. Please check P4 variables.\n";
- exit -1;
- }
- $client = &Icp4::p4client();
- $support = "ryu\@cswitch.com";
-
- # check for outstanding changes
- if (!$opt{i} && &Icp4::outstanding_changes()) {
- exit -1;
- }
-
- if ($islayout = &Icp4::is_layout_view()) {
-
- # At this point, the raw_list contains only attr and iccel files
- # that are known to exist in unix.
- get_raw_list();
- if ($opt{D}) {
- &Icp4::list_debug_print("raw_list", @raw_list);
- }
-
- # revert list is a subset of raw_list and are files that have not been modified
- get_revert_list();
- if ($opt{D}) {
- &Icp4::list_debug_print("revert_list", @revert_list);
- }
-
- # edit list is a subset of raw_list and are files that have been modified
- get_edit_list();
- if ($opt{D}) {
- &Icp4::list_debug_print("edit_list", @edit_list);
- }
-
- # add list is a subset of raw_list and new files to p4
- get_add_list();
- if ($opt{D}) {
- &Icp4::list_debug_print("add_list", @add_list);
- }
-
- # Bring up the form. all files listed will be
- # reverted if not changed, added if it's new, and then submitted.
- p4_add_submit_revert();
-
- } else {
- old_p4ci();
- }
-
- exit 0;
- }
-
-
- sub get_raw_list {
- my ($cell, $orig_cell, $path);
- my ($attr_file, $orig_attr_file, $ic_pat, $ic_file);
- my ($openStat, $expectedStat);
- my (@keep_list, $i, $s, $orig_cnt, $exists);
-
- $cells = "";
- foreach $cell (@ARGV) {
-
- # get rid of any trailing "/" and convert to full path
- $cell =~ s/\/$//;
- $path = Cwd::abs_path(dirname($cell));
-
- $orig_cell = $cell;
-
- # escape the name for p4
- if ($cell =~ /\$/) {
- $cell =~ s/\$/\\\$/g;
- if ($opt{D}) {
- print "# DEBUG: path = $path\n";
- print "# DEBUG: cell = $cell\n";
- print "# DEBUG: orig_cell = $orig_cell\n";
- }
- }
-
- if (-d $orig_cell) {
-
- # remove any .iclck files
- unlink <${orig_cell}/.*.iclck>;
-
- $cells = $cells . "${cell}/... ";
-
- #$cell_attr = $cell . $attr_sfx;
- $ic_pat = $cell . $cell_sfx;
-
- $orig_attr_file = "${orig_cell}/${orig_cell}${attr_sfx}";
- $attr_file = "${cell}/${cell}${attr_sfx}";
-
- if (has_lckfiles($cell)) {
- print "WARNING: Cell \"$cell\" is locked by icstudio. Skipping cell \"$cell\".\n";
- next;
- }
-
- # workaround for some attribute files that have .s
- if (! -f "$orig_attr_file") {
- print "WARNING: $orig_attr_file not found. Trying the .s trick.\n";
- $orig_attr_file = "${orig_cell}/${orig_cell}.s${attr_sfx}";
- $attr_file = "${cell}/${cell}.s${attr_sfx}";
- if (! -f "$orig_attr_file") {
- print "WARNING: $orig_attr_file not found either. Skipping \"$orig_cell\".\n";
- next;
- } else {
- print "INFO: Found $orig_attr_file.\n";
- }
- }
-
- &Icp4::get_keep_list($orig_attr_file, \@keep_list);
-
- if ($opt{D}) {
- &Icp4::list_debug_print("keep_list", @keep_list);
- }
-
- $orig_cnt = $#keep_list;
- for ($i=0; $i <= ($orig_cnt - $keep); $i++) {
- shift @keep_list;
- }
-
- if ($opt{D}) {
- print "# DEBUG: After trimming ... $#keep_list\n";
- &Icp4::list_debug_print("keep_list", @keep_list);
- }
-
- # existence check for @keep_list files
- $exists = 1;
- foreach $i (@keep_list) {
- $ic_file = "$path/$orig_cell/$i";
- if (! -f $ic_file) {
- $exists = 0;
- print "ERROR: \"$ic_file\" not found. Skipping cell \"$cell\".\n";
- last;
- }
- }
-
- if ($exists) {
- $s = "${path}/${orig_attr_file}";
- push (@raw_list, $s);
- $file_status{$s} = "raw";
- foreach $i (@keep_list) {
- $s = "${path}/${orig_cell}/$i";
- push (@raw_list, $s);
- $file_status{$s} = "raw";
- }
- }
- }
- }
- close FOUT;
- }
-
-
- sub get_revert_list {
- my($rawfile) = ".rawlist.$$";
- my ($s);
-
- open (FOUT, ">$rawfile") or die "ERROR: cannot open $rawfile.";
- foreach $s (@raw_list) {
- print FOUT "$s\n";
- }
- close FOUT;
-
- open (REVERT, "p4 -x $rawfile revert -a -n 2>&1 |") or die "ERROR: cannot run p4 revert.";
- while (<REVERT>) {
- if (($s) = /(.*)#\d+ - was edit, reverted/) {
- # change name
- $s =~ s#//depot#$client#;
- push (@revert_list, $s);
- if ($file_status{$s}) {
- $file_status{$s} = "revert";
- } else {
- die "INTERNAL ERROR: file status of $s not found. Please notify $support.\n";
- }
- }
- }
- close REVERT;
- unlink $rawfile unless ($opt{D});
- }
-
-
- sub get_edit_list {
- my (%p4files) = Icp4::fstat(@raw_list);
- my ($s);
- @edit_list = ();
- foreach $s (sort keys %p4files) {
- # print "# DEBUG: file \"$s\" has p4 status \"$p4files{$s}\".\n" if ($opt{D});
- if ($p4files{$s} eq 'edit') {
- if ($file_status{$s}) {
- if ($file_status{$s} ne 'revert') {
- push (@edit_list, $s);
- $file_status{$s} = "edit";
- }
- } else {
- die "INTERNAL ERROR: file status of \"$s\" not found during get_edit_list. Please notify $support.\n";
- }
- }
- }
- }
-
-
- sub get_add_list {
- my (%p4files) = Icp4::fstat(@raw_list);
- my ($s);
- @add_list = ();
- foreach $s (sort keys %p4files) {
- if (($p4files{$s} eq '???') || ($p4files{$s} eq 'delete')) {
- if ($file_status{$s}) {
- push (@add_list, $s);
- $file_status{$s} = "add";
- } else {
- die "INTERNAL ERROR: file status of \"$s\" not found during get_add_list. Please notify $support.\n";
- }
- }
- }
- }
-
-
- sub p4_add_submit_revert {
- my($file, $editor);
- my($proceed);
- my($extract);
- my($list_ptr, $s, $type, $depot_file);
-
- # create a changelist by combining list of opened
- # files with changelist template
- my($template) = ".template.$$";
- my($changelist) = ".changelist.$$";
-
- system("p4 change -o > $template");
-
- # When a workspace has nothing opened, the $template file will have no "Files:" line
- # Add it to the bottom of the file David Guan
- my($cnt);
- chop($cnt = `egrep -c Files $template`);
- if ($cnt == 1) {
- system("echo 'Files:' >> $template");
- }
-
- open (TEMPLATE, "$template") or die "ERROR: cannot open $template.";
- open (CHANGELIST, ">$changelist") or die "ERROR: cannot open $changelist.";
-
- while (<TEMPLATE>) {
- if (/^Files:/) {
- print CHANGELIST;
-
- foreach $file (sort keys %file_status) {
- $depot_file = $file;
- $depot_file =~ s#$client#//depot#;
- print CHANGELIST "\t$depot_file\t# add\n" if ($file_status{$file} eq "add");
- }
-
- foreach $file (sort keys %file_status) {
- $depot_file = $file;
- $depot_file =~ s#$client#//depot#;
- print CHANGELIST "\t$depot_file\t# edit\n" if ($file_status{$file} eq "edit");
- }
-
- last;
-
- } else {
- print CHANGELIST;
- }
- }
- close CHANGELIST;
-
- $editor = $ENV{'P4EDITOR'} ? $ENV{'P4EDITOR'} :
- $ENV{'EDITOR'} ? $ENV{'EDITOR'} : "vim" ;
-
- # now bring up the editor and have user say something nice
- system ("$editor $changelist");
-
- # Read the editted changelist, and look for the "<enter description here>".
- # If found, then do no p4 action, otherwise, create the real p4 changelist.
-
- open (CHANGELIST, "$changelist") or die "ERROR: cannot open $changelist.";
-
- $proceed = 1;
- $extract = 0;
- while (<CHANGELIST>) {
- if (/<enter description here>/) {
- $proceed = 0;
- next;
- }
-
- if (/^Files:/) {
- if ($proceed == 0) {
- print "ERROR: Change description missing. You must enter a description to continue.\n";
- exit -1;
- }
- $extract = 1;
- next;
- }
-
- if ($extract) {
- if (($s, $type) = /^\t(.*)\t# (add|edit)/) {
- $s =~ s#//depot#$client#;
- if ($type eq "add") {
- push (@user_add_list, $s);
- } else {
- push (@user_edit_list, $s);
- }
- # check the file are still under the same list
- if ($file_status{$s} ne $type) {
- print "ERROR: file \"$s\" should have been \"$file_status{$s}\" but was set to \"$type\".\n";
- exit -1;
- }
- next;
- }
- }
- }
- close CHANGELIST;
-
- if ($opt{D}) {
- &Icp4::list_debug_print("user_add_list", @user_add_list);
- &Icp4::list_debug_print("user_edit_list", @user_edit_list);
- }
-
- # now do these together
- p4_add(\@user_add_list) if ($#user_add_list >= 0);
- p4_submit($changelist) if (($#user_add_list >= 0) || ($#user_edit_list >= 0));
- p4_revert_cells() if (!$opt{r});
-
- # cleanup
- unlink $template unless ($opt{D});
- unlink $changelist unless ($opt{D});
- }
-
-
- sub p4_add {
- my($list_ptr) = @_;
- my($s, $cmd);
- my($template) = ".addfiles.$$";
- open (TEMPLATE, ">$template") or die "ERROR: cannot open $template.";
- foreach $s (@{$list_ptr}) {
- print TEMPLATE "$s\n";
- }
- close TEMPLATE;
- $cmd = "p4 -x $template add $nflag";
- if ($opt{n}) {
- print "INFO: Adding (not run) new files using (\"$cmd\")\n";
- } else {
- print "INFO: Adding new files using (\"$cmd\")\n";
- }
- system $cmd;
- unlink $template unless ($opt{D});
- }
-
-
- sub p4_submit {
- my ($changelist) = @_;
- my ($s, $cmd);
- $cmd = "p4 submit $rflag -i < $changelist";
- if ($opt{n}) {
- print "INFO: Submitting (not run) changes using (\"$cmd\")\n";
- } else {
- print "INFO: Submitting changes using (\"$cmd\")\n";
- }
- system $cmd unless ($opt{n});
- }
-
-
- # Unused: this may leave some files in edit mode because p4co did 'p4 edit cell/...'
- # Better to use p4_revert_cells instead
- sub p4_revert {
- my($list_ptr) = @_;
- my($s, $cmd);
- my($template) = ".revertfiles.$$";
- open (TEMPLATE, ">$template") or die "ERROR: cannot open $template.";
- foreach $s (@{$list_ptr}) {
- print TEMPLATE "$s\n";
- }
- close TEMPLATE;
- $cmd = "p4 -x $template revert -a $nflag";
- if ($opt{n}) {
- print "INFO: Reverting (not run) unchanged files using (\"$cmd\")\n";
- } else {
- print "INFO: Reverting unchanged files using (\"$cmd\")\n";
- }
- system $cmd;
- unlink $template unless ($opt{D});
- }
-
-
- sub p4_revert_cells {
- my($cmd);
- $cmd = "p4 revert -a $nflag $cells > /dev/null 2>&1";
- if ($opt{n}) {
- print "INFO: Reverting (not run) all unchanged files using (\"$cmd\")\n";
- } else {
- print "INFO: Reverting all unchanged files using (\"$cmd\")\n";
- }
- system $cmd;
- }
-
-
- # has_lckfiles --
- # returns true if lck files found
- sub has_lckfiles {
- my($dir) = @_;
-
- open(FIND, "find $dir -name \*.lck\* -print |") or die "ERROR: cannot run find.";
- while (<FIND>) {
- return 1;
- }
- return 0;
- }
-
- # ----------------------------------------------------------------------------------------
-
- # TODO: support schematics
-
- # old_p4ci --
- # old p4ci, which is used for schematics
- sub old_p4ci {
-
- my ($p4local_flag, $cell, $cell_dirname);
-
- if ($P4CI_LOG) {
- $p4local_flag = "-L $ENV{HOME}/p4ci.log";
- }
-
- $cells = "";
-
- # Let's check for lck files first. And if found any, just quit
- foreach $cell (@ARGV) {
- $cell_dirname = $cell;
- if ($cell =~ /\$/) {
- $cell =~ s/\$/\\\$/g;
- }
-
- if (-d $cell_dirname) {
- if (has_lckfiles($cell)) {
- print "ERROR: Cell \"$cell\" is locked by icstudio. Please remove lock and try again.\n";
- exit -1;
- }
- }
- }
-
- foreach $cell (@ARGV) {
- $cell_dirname = $cell;
- if ($cell =~ /\$/) {
- $cell =~ s/\$/\\\$/g;
- }
-
- if (-d $cell_dirname) {
-
- # remove any .iclck files
- unlink <${cell_dirname}/.*.iclck>;
-
- # add any new $cell.* files ...
- system "p4local $p4local_flag -a ${cell}.*";
-
- # or files under the $cell directory
- if ((system "p4local $p4local_flag -a $cell") == 0) {
- $cells = $cells . " ${cell}.* ${cell}/...";
- } else {
- # some bad happened, maybe a lck file found
- print "INFO: No operation performed for cell $cell.\n";
- }
- }
- }
-
- if ($cells ne "") {
- if (!$opt{r}) {
- print "INFO: Reverting any unmodified files (\"p4 revert $nflag -a $cells\")\n";
- system "p4 revert $nflag -a $cells";
- }
-
- &Icp4::submit_open_files($cells, $rflag);
- }
-
- exit 0;
- }