Initial commit
[clearscm.git] / cc / triggers / EvilTwin.pl
1 #!/usr/bin/perl -w
2 ################################################################################
3 #
4 # File:         EvilTwin.pl,v
5 # Revision:     1.1.1.1
6 # Description:  This trigger checks for evil twins. And evil twin can occur when
7 #               a user checks in an element which matches an element name on
8 #               some other branch of the directory that is invisible in the
9 #               current view.
10 # Trigger Type: All element
11 # Operation:    Preop lnname
12 # Author:       Andrew@DeFaria.com
13 # Created:      May 24, 2004
14 # Modified:     2007/05/17 07:45:48
15 # Language:     Perl
16 #
17 # (c) Copyright 2004, Andrew@DeFaria.com, all rights reserved
18 #
19 ################################################################################
20 use strict;
21 use File::Basename;
22
23 # Ensure that the view-private file will get named back on rejection.
24 BEGIN {
25   END {
26     rename "$ENV{CLEARCASE_PN}.mkelem", "$ENV{CLEARCASE_PN}"
27       if $? && ! -e "ENV{CLEARCASE_PN}" && -e "$ENV{CLEARCASE_PN}.mkelem";
28   } # END
29 } # BEGIN
30
31 # Check to see if we are running on Windows
32 my $windows     = ($^O =~ /MSWin/) ? "yes" : "no";
33
34 # Delimeters and null are different on the different OSes
35 my $dir_delim   = $windows eq "yes" ? "\\"   : "/";
36 my $dir_delim_e = $windows eq "yes" ? "\\\\" : "\/";
37 my $null        = $windows eq "yes" ? "NUL"  : "/dev/null";
38
39 # This is called only if an evil twin is detected. It simply writes
40 # out information about the evil twin to a log file. Eventually we
41 # will turn this off.
42 sub Log {
43   my $msg = shift;
44
45   my $time = localtime;
46   my $user = $ENV {CLEARCASE_USER};
47   my $logpath = $windows eq "yes" ? "\\\\p01ccvob.usa.hp.com\\vobstore\\triggers\\" :
48                                     "/net/p01ccvob.usa.hp.com/vobstore/triggers/";
49   my $logfile = $logpath . "EvilTwin.log";
50   open LOG, ">>$logfile" or die "Unable to open $logfile";
51
52   print LOG "$time: $user: $msg\n";
53
54   close LOG;
55 } # Log
56
57 # Get Clearcase Environment variables needed
58 my $pname = $ENV {CLEARCASE_PN};
59
60 #Log "pname = $pname";
61
62 # Get element and parent directory name
63 my ($element_name, $parent) = fileparse ($pname);
64 #Log "element_name = $element_name";
65 #Log "parent = $parent";
66
67 # At this point parent will either end with "\.\" on Windows ("/./" on
68 # Unix) or a single "\" Windows ("/" on Unix).  Windows has a strange
69 # situation when the trailing part of parent is = "\". It ends up
70 # quoting the double quote and causes the execution of the lsvtree to
71 # fail. We must detect this and add on an additional "\".
72 if ($parent =~ m/$dir_delim_e\.$dir_delim_e$/) {
73   $parent =~ s/$dir_delim_e\.$dir_delim_e$/$dir_delim_e/;
74 } elsif ($parent =~ m/\\$/) {
75   $parent .= $dir_delim;
76 } # if
77
78 #Log "parent = $parent";
79
80 # Look for evil twins
81 my $status;
82 my $possible_dup;
83
84 # Get list of all branches for the parent directory. We will search
85 # these for possible evil twins.
86 my @parent_dir_branches = `cleartool lsvtree -all -s "$parent"`;
87
88 # Fixup parent by removing trailing delimiters
89 $parent =~ s/\\\\$/\\/;
90
91 foreach (@parent_dir_branches) {
92   chomp;
93   chop if /\r/;
94 #  Log $_;
95 } # foreach
96
97 my $evil_twin = 1;
98
99 #Log "Checking parent directories";
100 foreach (@parent_dir_branches) {
101   chomp;
102
103   $possible_dup = $_ . $dir_delim . $element_name;
104 #  Log "possible_dup = $possible_dup";
105
106   # View extended pathnames don't work from snapshot views. While
107   # using cleartool ls is slower it also has the benefit of respecting
108   # the case sensitivity of MVFS.
109 #  Log "Doing ct ls";
110   $status = (system "cleartool ls -s $possible_dup > $null 2>&1") >> 8;
111
112   if ($status eq 0) {
113     # We found something related to $element_name. Now check to see if
114     # this something is a branch name
115 #    Log "Found something";
116     my $type = `cleartool desc -fmt %m $possible_dup 2>&1`;
117     chomp ($type);
118
119     if ("$type" ne "branch") {
120       # If it's not a branch then we've found an evil twin - set $status
121       # to 1 indicating this and break out.
122 #      Log "Evil twin found!";
123       $evil_twin = 0;
124       last;
125     } # if
126 #  } else {
127 #    Log "status = $status";
128   } # if
129 } # foreach
130
131 # Exit 0 if the evil twin is not found
132 exit 0 if $evil_twin;
133
134 # Possible duplicate element is found on invisible branch(es).
135 my $prompt;
136 my $nl = $windows eq "yes" ? "\\n" : "\n";
137 $parent = "." if $parent eq "";
138 $prompt  = "The element $element_name already exists for the directory \'$parent\'$nl";
139 $prompt .= "in another branch as ($possible_dup).$nl$nl";
140 $prompt .= "You could either merge the parent directories or create a Clearcase hardline to$nl";
141 $prompt .= "that element.$nl$nl";
142 $prompt .= "For more information about this condition see:$nl$nl";
143 $prompt .= "http://ilmwiki.usa.hp.com/wiki/ClearCase_Evil_Twins$nl$nl";
144 $prompt .= "If you feel you really need to perform this action please submit a request$nl";
145 $prompt .= "through SourceForge at:$nl$nl";
146 $prompt .= "http://plesf01srv.usa.hp.com/sf/tracker/do/listArtifacts/projects.eng_tools_support/tracker.clearcase";
147
148 Log "Evil twin detected in $parent. Twin: $possible_dup";
149 system ("clearprompt yes_no -mask abort -default abort -newline -prompt \"$prompt\"");
150
151 exit 1;