monotone

monotone Commit Details

Date:2009-02-06 21:07:42 (10 years 4 months ago)
Author:Tony Cooper
Branch:net.venge.monotone.contrib.mtn-browse
Commit:9cebff648f0035afc47937e3169d06c09fbae4dd
Parents: 829f59f1d4c0b25af7dc045ccbe0195ed5ab08a7
Message:- Annotate window now offers a lot more options via its menu for accessing file

and revision change logs and comparing between the current file or revision
its parent version.
- Put some string constants under locale control, they were missed off before by
accident.
- Made sure that all calls to dialogs' run method are granted mouse input by the
WindowManager object.
- The mtn warning handler can be suppressed by the use of a global variable
(which can be set using local).
- Now guard against no external comparison helper application being setup.
- Refactored some code in History.pm to better help support the new annotate
window options.
Changes:
Mlib/perl/Annotate.pm (5 diffs)
Mlib/perl/ComboAutoCompletion.pm (1 diff)
Mlib/perl/Common.pm (2 diffs)
Mlib/perl/FindFiles.pm (6 diffs)
Mlib/perl/FindText.pm (2 diffs)
Mlib/perl/Globals.pm (2 diffs)
Mlib/perl/History.pm (15 diffs)
Mlib/perl/Preferences.pm (1 diff)
Mmtn-browse (4 diffs)

File differences

lib/perl/Annotate.pm
5454
5555
5656
57
58
59
5760
5861
5962
......
9699
97100
98101
102
103
99104
100
105
101106
102107
103108
......
108113
109114
110115
111
116
117
118
119
112120
113121
114122
......
276284
277285
278286
279
287
288
289
290
291
280292
281293
282294
......
285297
286298
287299
288
300
301
302
303
304
305
306
307
308
309
310
311
312
313
289314
290
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
291344
292
293
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
294368
295
296
369
370
371
297372
298
299
300
301
302
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
303395
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
324418
325
326
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
327436
328
329
330
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
331461
332
333
334
335
336
462
463
464
465
466
467
468
469
470
471
472
337473
474
475
476
338477
339478
340479
341480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
342679
343680
344681
# Private routines.
sub annotation_textview_populate_popup_cb($$$);
sub annotation_textview_popup_menu_item_cb($$);
sub compare_file_with_previous($$);
sub compare_revision_with_parent($$);
sub get_annotation_window();
sub mtn_annotate($$$$);
#
local $instance->{in_cb} = 1;
$instance->{mtn} = $mtn;
$instance->{file_name} = $file_name;
$instance->{revision_id} = $revision_id;
$instance->{window}->set_title(__x("Annotated Listing Of {file}",
file => $file_name));
file => $instance->{file_name}));
$instance->{window}->show_all();
$wm->make_busy($instance, 1);
$instance->{appbar}->set_status(__("Annotating file"));
$wm->update_gui();
mtn_annotate(\@lines, $mtn->get_db_name(), $revision_id, $file_name);
mtn_annotate(\@lines,
$mtn->get_db_name(),
$revision_id,
$instance->{file_name});
# Find the longest line for future padding and also split each line into
# their prefix and text parts.
# the change log of the revision responsible for the text directly under
# the mouse cursor.
$menu_item = Gtk2::MenuItem->new("Display Change _Log");
$separator = Gtk2::SeparatorMenuItem->new();
$separator->show();
$menu->append($separator);
$menu_item = Gtk2::MenuItem->new(__("Display Change _Log"));
if (! defined($revision_part))
{
$menu_item->set_sensitive(FALSE);
{
$menu_item->signal_connect
("activate",
sub {
\&annotation_textview_popup_menu_item_cb,
{instance => $instance,
cb => sub {
my($instance, $revision_id) = @_;
display_change_log($instance->{mtn},
$revision_id,
"",
undef);
},
progress_message => __("Displaying change log"),
revision_part => $revision_part});
}
$menu_item->show();
$menu->append($menu_item);
my($widget, $details) = @_;
$menu_item = Gtk2::MenuItem->new(__("Display File _History"));
if (! defined($revision_part))
{
$menu_item->set_sensitive(FALSE);
}
else
{
$menu_item->signal_connect
("activate",
\&annotation_textview_popup_menu_item_cb,
{instance => $instance,
cb => sub {
my($instance, $revision_id) = @_;
my $old_file_name;
$instance->{mtn}->get_corresponding_path
(\$old_file_name,
$instance->{revision_id},
$instance->{file_name},
$revision_id);
display_file_change_history
($instance->{mtn},
$revision_id,
$old_file_name);
},
progress_message => __("Displaying file history"),
revision_part => $revision_part});
}
$menu_item->show();
$menu->append($menu_item);
return if ($details->{instance}->{in_cb});
local $details->{instance}->{in_cb} = 1;
$menu_item = Gtk2::MenuItem->new(__("Display _Revision History"));
if (! defined($revision_part))
{
$menu_item->set_sensitive(FALSE);
}
else
{
$menu_item->signal_connect
("activate",
\&annotation_textview_popup_menu_item_cb,
{instance => $instance,
cb => sub {
my($instance, $revision_id) = @_;
display_revision_change_history
($instance->{mtn},
undef,
$revision_id);
},
progress_message => __("Displaying revision history"),
revision_part => $revision_part});
}
$menu_item->show();
$menu->append($menu_item);
my @revision_ids;
my $wm = WindowManager->instance();
$separator = Gtk2::SeparatorMenuItem->new();
$separator->show();
$menu->append($separator);
$wm->make_busy($details->{instance}, 1);
$instance->{appbar}->
push($instance->{appbar}->get_status()->get_text());
$instance->{appbar}->set_status(__("Finding change log"));
$wm->update_gui();
$menu_item =
Gtk2::MenuItem->new(__("Compare File With Previous _Version"));
if (! defined($revision_part))
{
$menu_item->set_sensitive(FALSE);
}
else
{
$menu_item->signal_connect
("activate",
\&annotation_textview_popup_menu_item_cb,
{instance => $instance,
cb => sub {
my($instance, $revision_id) = @_;
compare_file_with_previous($instance,
$revision_id);
},
progress_message => __("Doing file comparison"),
revision_part => $revision_part});
}
$menu_item->show();
$menu->append($menu_item);
$details->{instance}->{mtn}->
select(\@revision_ids, "i:" . $details->{revision_part});
if (scalar(@revision_ids) == 1)
{
display_change_log($details->{instance}->{mtn},
$revision_ids[0],
"",
undef);
}
else
{
my $dialog = Gtk2::MessageDialog->new
($instance->{window},
["modal"],
"warning",
"close",
__("Cannot access unique revision id."));
$dialog->run();
$dialog->destroy();
}
$menu_item =
Gtk2::MenuItem->new(__("Compare Revision _With Parent"));
if (! defined($revision_part))
{
$menu_item->set_sensitive(FALSE);
}
else
{
$menu_item->signal_connect
("activate",
\&annotation_textview_popup_menu_item_cb,
{instance => $instance,
cb => sub {
my($instance, $revision_id) = @_;
compare_revision_with_parent
($instance, $revision_id);
},
progress_message => __("Doing revision comparison"),
revision_part => $revision_part});
}
$menu_item->show();
$menu->append($menu_item);
$instance->{appbar}->pop();
$wm->make_busy($details->{instance}, 0);
}
#
##############################################################################
#
# Routine - annotation_textview_popup_menu_item_cb
#
# Description - Callback routine called when the user selects an item on
# the annotation textview's popup menu.
#
# Data - $widget : The widget object that received the signal.
# $menu : The Gtk2::Menu widget that is to be updated.
# $details : A reference to an anonymous hash containing the
# window instance, callback routine, progress
# message and the revision start string that is
# associated with this widget.
#
##############################################################################
},
{instance => $instance,
revision_part => $revision_part});
sub annotation_textview_popup_menu_item_cb($$)
{
my($widget, $details) = @_;
return if ($details->{instance}->{in_cb});
local $details->{instance}->{in_cb} = 1;
my @revision_ids;
my $wm = WindowManager->instance();
$wm->make_busy($details->{instance}, 1);
$details->{instance}->{appbar}->
push($details->{instance}->{appbar}->get_status()->get_text());
$details->{instance}->{appbar}->set_status($details->{progress_message});
$wm->update_gui();
$details->{instance}->{mtn}->
select(\@revision_ids, "i:" . $details->{revision_part});
if (scalar(@revision_ids) == 1)
{
$details->{cb}($details->{instance}, $revision_ids[0]);
}
$menu_item->show();
$separator = Gtk2::SeparatorMenuItem->new();
$separator->show();
$menu->append($separator);
$menu->append($menu_item);
else
{
my $dialog = Gtk2::MessageDialog->new
($details->{instance}->{window},
["modal"],
"warning",
"close",
__("Cannot access unique revision id."));
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
}
$details->{instance}->{appbar}->pop();
$wm->make_busy($details->{instance}, 0);
}
#
##############################################################################
#
# Routine - compare_file_with_previous
#
# Description - Compare the annotate file at the specified version with the
# previous version of the file.
#
# Data - $instance : The window instance that is associated with
# the annotation window.
# $revision_id : The revision id on which this file changed.
#
##############################################################################
sub compare_file_with_previous($$)
{
my($instance, $revision_id) = @_;
my(@chg_ancestors,
$file_name,
$old_file_name,
@parents);
my $wm = WindowManager->instance();
# Remember that a warning is generated when one goes back beyond a file's
# addition revision, so temporarily disable the warning handler.
{
local $suppress_mtn_warnings = 1;
# First get the name of the file at the specified revision (it might
# have been moved or renamed).
$instance->{mtn}->get_corresponding_path(\$file_name,
$instance->{revision_id},
$instance->{file_name},
$revision_id);
# Get the revision's parent and then find out when the file last
# changed.
$instance->{mtn}->parents(\@parents, $revision_id);
if (scalar(@parents) > 1)
{
my $dialog = Gtk2::MessageDialog->new
($instance->{window},
["modal"],
"info",
"close",
__("The selected revision has more than one parent.\n"
. "I will display the file's history so you can select\n"
. "the specific parent revision."));
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
display_file_change_history($instance->{mtn},
$revision_id,
$file_name);
return;
}
elsif (scalar(@parents) == 0)
{
my $dialog = Gtk2::MessageDialog->new
($instance->{window},
["modal"],
"info",
"close",
__("The selected revision has no parents."));
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
return;
}
$instance->{mtn}->get_content_changed(\@chg_ancestors,
$parents[0],
$file_name);
if (scalar(@chg_ancestors) > 1)
{
my $dialog = Gtk2::MessageDialog->new
($instance->{window},
["modal"],
"info",
"close",
__("The current version of the file probably\n"
. "resulted from a merge as it is directly\n"
. "descended from multiple versions.\n"
. "I will display the file's history so you\n"
. "can select the specific parent revision."));
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
display_file_change_history($instance->{mtn},
$revision_id,
$file_name);
return;
}
elsif (scalar(@chg_ancestors) == 0)
{
my $dialog = Gtk2::MessageDialog->new
($instance->{window},
["modal"],
"info",
"close",
__("The selected file version has no ancestors."));
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
return;
}
}
# Ok now make sure the file name hasn't changed. If it has then use the
# external differences tool.
$instance->{mtn}->get_corresponding_path(\$old_file_name,
$revision_id,
$file_name,
$chg_ancestors[0]);
if ($old_file_name ne $file_name)
{
display_renamed_file_comparison($instance->{window},
$instance->{mtn},
$chg_ancestors[0],
$old_file_name,
$revision_id,
$file_name);
}
else
{
display_revision_comparison($instance->{mtn},
$chg_ancestors[0],
$revision_id,
$file_name);
}
}
#
##############################################################################
#
# Routine - compare_revision_with_parent
#
# Description - Compare the revision at the specified version with its
# parent.
#
# Data - $instance : The window instance that is associated with
# the annotation window.
# $revision_id : The revision id that is to be compared
# against its parent.
#
##############################################################################
sub compare_revision_with_parent($$)
{
my($instance, $revision_id) = @_;
my @parents;
my $wm = WindowManager->instance();
# First get the revision's parent(s).
$instance->{mtn}->parents(\@parents, $revision_id);
if (scalar(@parents) > 1)
{
my $dialog = Gtk2::MessageDialog->new
($instance->{window},
["modal"],
"info",
"close",
__("The selected revision has more than one parent.\n"
. "I will display the revision's history so you can select\n"
. "the specific parent revision."));
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
display_revision_change_history($instance->{mtn}, undef, $revision_id);
return;
}
elsif (scalar(@parents) == 0)
{
my $dialog = Gtk2::MessageDialog->new
($instance->{window},
["modal"],
"info",
"close",
__("The selected revision has no parents."));
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
return;
}
# Ok now compare the revisions and display the results.
display_revision_comparison($instance->{mtn}, $parents[0], $revision_id);
}
#
##############################################################################
#
# Routine - get_annotation_window
#
# Description - Creates or prepares an existing annotation window for use.
lib/perl/ComboAutoCompletion.pm
174174
175175
176176
177
177
178178
179179
180180
181181
182182
183183
184
184
185185
186186
187187
188188
189189
190190
191
191
192192
193193
194194
$combo = $instance->{branch_comboboxentry};
$change_state = BRANCH_CHANGED;
$combo_details = $instance->{branch_combo_details};
$name = "branch";
$name = __("branch");
}
elsif ($widget == $instance->{revision_comboboxentry})
{
$combo = $instance->{revision_comboboxentry};
$change_state = REVISION_CHANGED;
$combo_details = $instance->{revision_combo_details};
$name = "revision";
$name = __("revision");
}
elsif ($widget == $instance->{directory_comboboxentry})
{
$combo = $instance->{directory_comboboxentry};
$change_state = DIRECTORY_CHANGED;
$combo_details = $instance->{directory_combo_details};
$name = "directory";
$name = __("directory");
}
else
{
lib/perl/Common.pm
611611
612612
613613
614
614
615
615616
616617
617618
......
11551156
11561157
11571158
1158
1159
1160
11591161
11601162
11611163
# Create a popup menu with the search option in it.
$menu = Gtk2::Menu->new();
$menu_item = Gtk2::MenuItem->new("Select As Search Column");
$menu_item =
Gtk2::MenuItem->new(__("Select As Search Column"));
$menu->append($menu_item);
$menu_item->show();
"warning",
"close",
__("Your preferences could not be saved:\n") . $@);
$dialog->run();
WindowManager->instance()->allow_input
(sub { $dialog->run(); });
$dialog->destroy();
}
}
lib/perl/FindFiles.pm
10451045
10461046
10471047
1048
1048
1049
10491050
10501051
10511052
......
10631064
10641065
10651066
1066
1067
10671068
10681069
10691070
......
10861087
10871088
10881089
1089
1090
10901091
10911092
10921093
......
11041105
11051106
11061107
1107
1108
11081109
11091110
11101111
......
11241125
11251126
11261127
1127
1128
11281129
11291130
11301131
......
11381139
11391140
11401141
1141
1142
11421143
11431144
11441145
my($instance, $query) = @_;
my($re_text);
my $re_text;
my $wm = WindowManager->instance();
# Check that the file name glob is valid.
"close",
__x("`{pattern}' is an invalid\nfile name pattern.",
pattern => $query->{file_glob}));
$dialog->run();
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
return;
}
"close",
__x("`{pattern}' is an invalid\ncontent search pattern.",
pattern => $query->{contents_pattern}));
$dialog->run();
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
return;
}
"close",
__("The `between' dates are either\n"
. "the same or the wrong way round."));
$dialog->run();
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
return;
}
"close",
__x("A duration of {months} months is too long.",
months => $query->{period}));
$dialog->run();
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
return;
}
"close",
__x("A duration of {years} years is too long.",
years => $query->{period}));
$dialog->run();
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
return;
}
lib/perl/FindText.pm
169169
170170
171171
172
172
173173
174174
175175
......
241241
242242
243243
244
244
245245
246246
247247
}
}
# Ammend the textview object to reflect its file text enabled/disabled
# Amend the textview object to reflect its file text enabled/disabled
# state.
if ($enable)
# Add a `Find' option to the right-click menu that displays the find text
# dialog.
$menu_item = Gtk2::MenuItem->new("_Find");
$menu_item = Gtk2::MenuItem->new(__("_Find"));
if ($widget->{find_text_disabled})
{
$menu_item->set_sensitive(FALSE);
lib/perl/Globals.pm
110110
111111
112112
113
114
115
116
113117
114118
115119
......
135139
136140
137141
142
138143
139144
140145
our $mime_match_table;
# Whether Monotone warnings should be suppressed or not.
our $suppress_mtn_warnings;
# ***** PACKAGE INFORMATION *****
use base qw(Exporter);
$line_image
$mime_match_table
$mono_font
$suppress_mtn_warnings
$tmp_dir
$tooltips
$user_preferences)]);
lib/perl/History.pm
8080
8181
8282
83
8384
85
8486
8587
8688
8789
88
8990
90
91
9192
9293
9394
......
356357
357358
358359
359
360
361
362
360
361
362
363
364
365
363366
364367
365368
......
500503
501504
502505
503
506
504507
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
508
779509
780510
781511
......
794524
795525
796526
797
527
798528
799529
800530
......
1216946
1217947
1218948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
12191264
12201265
12211266
......
13171362
13181363
13191364
1320
1365
1366
1367
1368
1369
1370
13211371
13221372
13231373
......
15561606
15571607
15581608
1559
1609
15601610
15611611
15621612
15631613
1564
1614
15651615
1566
1616
15671617
15681618
15691619
......
15721622
15731623
15741624
1575
1625
15761626
15771627
15781628
15791629
15801630
15811631
1582
1632
15831633
15841634
15851635
......
15881638
15891639
15901640
1591
1641
15921642
15931643
15941644
......
15961646
15971647
15981648
1599
1649
16001650
16011651
16021652
16031653
1604
1654
16051655
16061656
16071657
......
18201870
18211871
18221872
1823
1873
1874
1875
1876
18241877
18251878
18261879
......
18341887
18351888
18361889
1837
1890
18381891
18391892
1840
1841
1893
1894
1895
1896
1897
1898
18421899
18431900
18441901
......
18461903
18471904
18481905
1906
18491907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
18501927
18511928
18521929
......
18561933
18571934
18581935
1859
1936
18601937
18611938
18621939
18631940
1864
1941
18651942
18661943
18671944
......
18721949
18731950
18741951
1875
1952
18761953
18771954
18781955
18791956
1880
1957
18811958
18821959
18831960
18841961
18851962
1886
1963
18871964
1888
1965
18891966
18901967
18911968
# Public routines.
sub display_file_change_history($$$);
sub display_renamed_file_comparison($$$$$$);
sub display_revision_change_history($$$);
sub display_revision_comparison($$$;$);
# Private routines.
sub compare_button_clicked_cb($$);
sub compare_revisions($$$;$);
sub comparison_revision_change_log_button_clicked_cb($$);
sub external_diffs($$$$$);
sub external_diffs($$$$$$);
sub external_diffs_button_clicked_cb($$);
sub file_comparison_combobox_changed_cb($$);
sub get_file_history_helper($$$);
$instance->{stop_button}->set_sensitive(TRUE);
$wm->update_gui();
$instance->{revision_hits} = {};
Monotone::AutomateStdio->register_error_handler(MTN_SEVERITY_WARNING);
get_file_history_helper($instance, $revision_id, \$instance->{file_name});
Monotone::AutomateStdio->register_error_handler(MTN_SEVERITY_ALL,
\&mtn_error_handler);
{
local $suppress_mtn_warnings = 1;
get_file_history_helper($instance,
$revision_id,
\$instance->{file_name});
}
$instance->{stop_button}->set_sensitive(FALSE);
# Sort the list.
#
##############################################################################
#
# Routine - history_list_button_clicked_cb
# Routine - display_revision_comparison
#
# Description - Callback routine called when the user clicks on any of the
# buttons displayed in the history list in a history window.
#
# Data - $widget : The widget object that received the signal.
# $details : A reference to an anonymous hash containing the
# window instance, revision and action that is
# associated with this widget.
#
##############################################################################
sub history_list_button_clicked_cb($$)
{
my($widget, $details) = @_;
my($instance,
$revision_id);
$instance = $details->{instance};
$revision_id = $details->{revision_id};
return if ($instance->{in_cb});
local $instance->{in_cb} = 1;
if ($details->{button_type} eq "1" || $details->{button_type} eq "2")
{
if ($details->{button_type} eq "1")
{
$instance->{first_revision_id} = $revision_id;
set_label_value($instance->{revision_id_1_value_label},
$revision_id);
if ($instance->{first_revision_id}
eq $instance->{second_revision_id})
{
$instance->{second_revision_id} = "";
set_label_value($instance->{revision_id_2_value_label}, "");
}
}
else
{
$instance->{second_revision_id} = $revision_id;
set_label_value($instance->{revision_id_2_value_label},
$revision_id);
if ($instance->{second_revision_id}
eq $instance->{first_revision_id})
{
$instance->{first_revision_id} = "";
set_label_value($instance->{revision_id_1_value_label}, "");
}
}
if ($instance->{first_revision_id} ne ""
&& $instance->{second_revision_id} ne "")
{
$instance->{compare_button}->set_sensitive(TRUE);
}
else
{
$instance->{compare_button}->set_sensitive(FALSE);
}
}
elsif ($details->{button_type} eq "browse-revision")
{
my($branch,
@certs_list);
# First find out what branch the revision is on (take the first one).
$instance->{mtn}->certs(\@certs_list, $revision_id);
$branch = "";
foreach my $cert (@certs_list)
{
if ($cert->{name} eq "branch")
{
$branch = $cert->{value};
last;
}
}
# Get a new browser window preloaded with the desired file.
get_browser_window($instance->{mtn}, $branch, $revision_id);
}
elsif ($details->{button_type} eq "browse-file")
{
my($branch,
@certs_list,
$dir,
$file,
$path_ref);
# First find out what branch the revision is on (take the first one).
$instance->{mtn}->certs(\@certs_list, $revision_id);
$branch = "";
foreach my $cert (@certs_list)
{
if ($cert->{name} eq "branch")
{
$branch = $cert->{value};
last;
}
}
# Split the file name into directory and file components.
$path_ref = $instance->{revision_hits}->{$revision_id};
$dir = dirname($$path_ref);
$dir = "" if ($dir eq ".");
$file = basename($$path_ref);
# Get a new browser window preloaded with the desired file.
get_browser_window($instance->{mtn},
$branch,
$revision_id,
$dir,
$file);
}
else
{
# Display the full revision change log.
display_change_log($instance->{mtn}, $revision_id);
}
}
#
##############################################################################
#
# Routine - compare_button_clicked_cb
#
# Description - Callback routine called when the user clicks on the
# revision comparison button in a history window.
#
# Data - $widget : The widget object that received the signal.
# $instance : The window instance that is associated with
# this widget.
#
##############################################################################
sub compare_button_clicked_cb($$)
{
my($widget, $instance) = @_;
return if ($instance->{in_cb});
local $instance->{in_cb} = 1;
my @revision_ids;
# Sort the revisions by date, oldest first.
@revision_ids = ($instance->{first_revision_id},
$instance->{second_revision_id});
$instance->{mtn}->toposort(\@revision_ids, @revision_ids);
# If a file is being compared and it has been renamed between the two
# comparison revisions then we have to fall back on the external helper
# application, otherwise we can use Monotone's comparison feature.
if (defined($instance->{file_name})
&& $instance->{revision_hits}->{$revision_ids[0]}
!= $instance->{revision_hits}->{$revision_ids[1]})
{
my($answer,
$dialog,
@manifest,
$new_file_id,
$old_file_id);
$dialog = Gtk2::MessageDialog->new
($instance->{window},
["modal"],
"question",
"yes-no",
__("The name of the selected file has changed\n"
. "between the two selected revisions and cannot\n"
. "be compared internally. Would you like to do\n"
. "the comparison using the external helper application?"));
$dialog->set_title(__("External Comparison"));
$answer = $dialog->run();
$dialog->destroy();
# Only continue if asked to do so.
if ($answer eq "yes")
{
# Get the manifests of the two revisions and look for the files in
# order to get their file ids.
$instance->{mtn}->get_manifest_of(\@manifest, $revision_ids[0]);
foreach my $entry (@manifest)
{
if ($entry->{name}
eq ${$instance->{revision_hits}->{$revision_ids[0]}})
{
$old_file_id = $entry->{file_id};
last;
}
}
$instance->{mtn}->get_manifest_of(\@manifest, $revision_ids[1]);
foreach my $entry (@manifest)
{
if ($entry->{name}
eq ${$instance->{revision_hits}->{$revision_ids[1]}})
{
$new_file_id = $entry->{file_id};
last;
}
}
# Make sure we have the file ids.
if (! defined($old_file_id) || ! defined ($new_file_id))
{
my $dialog;
$dialog = Gtk2::MessageDialog->new
($instance->{window},
["modal"],
"warning",
"close",
__("The file contents cannot be\n"
. "found in the select revisions.\n"
. "This should not be happening."));
$dialog->run();
$dialog->destroy();
return;
}
# Use the external helper application to compare the files.
external_diffs($instance,
${$instance->{revision_hits}->{$revision_ids[0]}},
$old_file_id,
${$instance->{revision_hits}->{$revision_ids[1]}},
$new_file_id);
}
}
else
{
# Use Monotone's comparison feature.
compare_revisions($instance->{mtn},
$revision_ids[0],
$revision_ids[1],
defined($instance->{file_name})
? ${$instance->{revision_hits}->
{$revision_ids[0]}}
: undef);
}
}
#
##############################################################################
#
# Routine - compare_revisions
#
# Description - Compares and then displays the differeneces between the two
# Description - Compares and then displays the differences between the two
# specified revisions, optionally restricting it to the
# specified file.
#
sub compare_revisions($$$;$)
sub display_revision_comparison($$$;$)
{
my($mtn, $revision_id_1, $revision_id_2, $file_name) = @_;
#
##############################################################################
#
# Routine - display_renamed_file_comparison
#
# Description - Compares and then displays the differences between two
# versions of a file that has either been renamed or moved
# somewhere between the specified revisions. The comparison
# has to be done with the external helper application.
#
# Data - $parent : The parent window widget for any dialogs
# that may appear.
# $mtn : The Monotone::AutomateStdio object that
# is to be used to get the files' details.
# $old_revision_id : The revision id for the older revision.
# $old_file_name : The name of the file on the older
# $new_revision_id : The revision id for the newer revision.
# $new_file_name : The name of the file on the newer
# revision.
#
##############################################################################
sub display_renamed_file_comparison($$$$$$)
{
my($parent,
$mtn,
$old_revision_id,
$old_file_name,
$new_revision_id,
$new_file_name) = @_;
my($answer,
$dialog,
@manifest,
$new_file_id,
$old_file_id);
my $wm = WindowManager->instance();
$dialog = Gtk2::MessageDialog->new
($parent,
["modal"],
"question",
"yes-no",
__("The name of the selected file has changed\n"
. "between the two selected revisions and cannot\n"
. "be compared internally. Would you like to do\n"
. "the comparison using the external helper application?"));
$dialog->set_title(__("External Comparison"));
$wm->allow_input(sub { $answer = $dialog->run(); });
$dialog->destroy();
# Only continue if asked to do so.
if ($answer eq "yes")
{
# Get the manifests of the two revisions and look for the files in
# order to get their file ids.
$mtn->get_manifest_of(\@manifest, $old_revision_id);
foreach my $entry (@manifest)
{
if ($entry->{name} eq $old_file_name)
{
$old_file_id = $entry->{file_id};
last;
}
}
$mtn->get_manifest_of(\@manifest, $new_revision_id);
foreach my $entry (@manifest)
{
if ($entry->{name} eq $new_file_name)
{
$new_file_id = $entry->{file_id};
last;
}
}
# Make sure we have the file ids.
if (! defined($old_file_id) || ! defined ($new_file_id))
{
my $dialog;
$dialog = Gtk2::MessageDialog->new
($parent,
["modal"],
"warning",
"close",
__("The file contents cannot be\n"
. "found in the selected revisions.\n"
. "This should not be happening."));
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
return;
}
# Use the external helper application to compare the files.
external_diffs($parent,
$mtn,
$old_file_name,
$old_file_id,
$new_file_name,
$new_file_id);
}
}
#
##############################################################################
#
# Routine - history_list_button_clicked_cb
#
# Description - Callback routine called when the user clicks on any of the
# buttons displayed in the history list in a history window.
#
# Data - $widget : The widget object that received the signal.
# $details : A reference to an anonymous hash containing the
# window instance, revision and action that is
# associated with this widget.
#
##############################################################################
sub history_list_button_clicked_cb($$)
{
my($widget, $details) = @_;
my($instance,
$revision_id);
$instance = $details->{instance};
$revision_id = $details->{revision_id};
return if ($instance->{in_cb});
local $instance->{in_cb} = 1;
if ($details->{button_type} eq "1" || $details->{button_type} eq "2")
{
if ($details->{button_type} eq "1")
{
$instance->{first_revision_id} = $revision_id;
set_label_value($instance->{revision_id_1_value_label},
$revision_id);
if ($instance->{first_revision_id}
eq $instance->{second_revision_id})
{
$instance->{second_revision_id} = "";
set_label_value($instance->{revision_id_2_value_label}, "");
}
}
else
{
$instance->{second_revision_id} = $revision_id;
set_label_value($instance->{revision_id_2_value_label},
$revision_id);
if ($instance->{second_revision_id}
eq $instance->{first_revision_id})
{
$instance->{first_revision_id} = "";
set_label_value($instance->{revision_id_1_value_label}, "");
}
}
if ($instance->{first_revision_id} ne ""
&& $instance->{second_revision_id} ne "")
{
$instance->{compare_button}->set_sensitive(TRUE);
}
else
{
$instance->{compare_button}->set_sensitive(FALSE);
}
}
elsif ($details->{button_type} eq "browse-revision")
{
my($branch,
@certs_list);
# First find out what branch the revision is on (take the first one).
$instance->{mtn}->certs(\@certs_list, $revision_id);
$branch = "";
foreach my $cert (@certs_list)
{
if ($cert->{name} eq "branch")
{
$branch = $cert->{value};
last;
}
}
# Get a new browser window preloaded with the desired file.
get_browser_window($instance->{mtn}, $branch, $revision_id);
}
elsif ($details->{button_type} eq "browse-file")
{
my($branch,
@certs_list,
$dir,
$file,
$path_ref);
# First find out what branch the revision is on (take the first one).
$instance->{mtn}->certs(\@certs_list, $revision_id);
$branch = "";
foreach my $cert (@certs_list)
{
if ($cert->{name} eq "branch")
{
$branch = $cert->{value};
last;
}
}
# Split the file name into directory and file components.
$path_ref = $instance->{revision_hits}->{$revision_id};
$dir = dirname($$path_ref);
$dir = "" if ($dir eq ".");
$file = basename($$path_ref);
# Get a new browser window preloaded with the desired file.
get_browser_window($instance->{mtn},
$branch,
$revision_id,
$dir,
$file);
}
else
{
# Display the full revision change log.
display_change_log($instance->{mtn}, $revision_id);
}
}
#
##############################################################################
#
# Routine - compare_button_clicked_cb
#
# Description - Callback routine called when the user clicks on the
# revision comparison button in a history window.
#
# Data - $widget : The widget object that received the signal.
# $instance : The window instance that is associated with
# this widget.
#
##############################################################################
sub compare_button_clicked_cb($$)
{
my($widget, $instance) = @_;
return if ($instance->{in_cb});
local $instance->{in_cb} = 1;
my @revision_ids;
# Sort the revisions by date, oldest first.
@revision_ids = ($instance->{first_revision_id},
$instance->{second_revision_id});
$instance->{mtn}->toposort(\@revision_ids, @revision_ids);
# If a file is being compared and it has been renamed between the two
# comparison revisions then we have to fall back on the external helper
# application, otherwise we can use Monotone's comparison feature.
if (defined($instance->{file_name})
&& $instance->{revision_hits}->{$revision_ids[0]}
!= $instance->{revision_hits}->{$revision_ids[1]})
{
display_renamed_file_comparison($instance->{window},
$instance->{mtn},
$revision_ids[0],
${$instance->{revision_hits}->
{$revision_ids[0]}},
$revision_ids[1],
${$instance->{revision_hits}->
{$revision_ids[1]}});
}
else
{
# Use Monotone's comparison feature.
display_revision_comparison($instance->{mtn},
$revision_ids[0],
$revision_ids[1],
defined($instance->{file_name})
? ${$instance->{revision_hits}->
{$revision_ids[0]}}
: undef);
}
}
#
##############################################################################
#
# Routine - file_comparison_combobox_changed_cb
#
# Description - Callback routine called when the user changes the value of
# Use the external helper application to compare the files.
external_diffs($instance, $file_name, $file_id_1, $file_name, $file_id_2);
external_diffs($instance->{window},
$instance->{mtn},
$file_name,
$file_id_1,
$file_name,
$file_id_2);
}
#
return if ($instance->{stop});
my(@changed_ancestors);
my @changed_ancestors;
$instance->{mtn}->get_content_changed(\@changed_ancestors,
$revision_id,
$$file_name_ref);
foreach my $revision (@changed_ancestors)
foreach my $chg_ancestor (@changed_ancestors)
{
if (! exists($instance->{revision_hits}->{$revision}))
if (! exists($instance->{revision_hits}->{$chg_ancestor}))
{
my @parents;
# bother if the ancestor revision is the same as the current one as
# we were passed the file name).
if ($revision ne $revision_id)
if ($chg_ancestor ne $revision_id)
{
my $file_name;
$instance->{mtn}->
get_corresponding_path(\$file_name,
$revision_id,
$$file_name_ref,
$revision);
$chg_ancestor);
$file_name_ref = \$file_name
if ($file_name ne $$file_name_ref);
}
# hash, this can be used later to refer to the correct file name
# for a given changed ancestor revision.
$instance->{revision_hits}->{$revision} = $file_name_ref;
$instance->{revision_hits}->{$chg_ancestor} = $file_name_ref;
set_label_value($instance->{numbers_value_label},
scalar(keys(%{$instance->{revision_hits}})));
# Now repeat for each parent, remembering to track file renames.
$instance->{mtn}->parents(\@parents, $revision);
$instance->{mtn}->parents(\@parents, $chg_ancestor);
foreach my $parent (@parents)
{
my $file_name;
$instance->{mtn}->get_corresponding_path(\$file_name,
$revision,
$chg_ancestor,
$$file_name_ref,
$parent);
$file_name_ref = \$file_name
# Description - Launch the external differences helper program, loading in
# the contents of the specified files.
#
# Data - $instance : The revision history window instance.
# Data - $parent : The parent window widget for any dialogs
# that may appear.
# $mtn : The Monotone::AutomateStdio object that is
# to be used to get the files' details.
# $old_file_name : The file name of the older version of the
# file.
# $old_file_id : Monotone's file id for the older version
sub external_diffs($$$$$)
sub external_diffs($$$$$$)
{
my($instance, $old_file_name, $old_file_id, $new_file_name, $new_file_id)
= @_;
my($parent,
$mtn,
$old_file_name,
$old_file_id,
$new_file_name,
$new_file_id) = @_;
my($cmd,
$data,
$new_file,
$old_fh,
$old_file);
my $wm = WindowManager->instance();
# Just check that we do actually have an external helper application to
# call.
if (! defined($user_preferences->{diffs_application})
|| $user_preferences->{diffs_application} =~ m/^\s*$/)
{
my $dialog = Gtk2::MessageDialog->new
($parent,
["modal"],
"warning",
"close",
__("Cannot call the external helper application\n"
. "to do the comparison as one has not been\n"
. "specified in the user's preferences."));
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
return;
}
# Generate temporary disk file names.
if (! defined($old_file = generate_tmp_path(__("OLDER_")
. basename($new_file_name))))
{
my $dialog = Gtk2::MessageDialog->new
($instance->{window},
($parent,
["modal"],
"warning",
__x("Cannot generate temporary file name:\n{error_message}.",
error_message => $!));
$dialog->run();
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
return;
}
|| ! defined($new_fh = IO::File->new($new_file, "w")))
{
my $dialog = Gtk2::MessageDialog->new
($instance->{window},
($parent,
["modal"],
"warning",
"close",
__x("{error_message}.", error_message => $!));
$dialog->run();
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
return;
}
binmode($old_fh);
binmode($new_fh);
$instance->{mtn}->get_file(\$data, $old_file_id);
$mtn->get_file(\$data, $old_file_id);
$old_fh->print($data);
$instance->{mtn}->get_file(\$data, $new_file_id);
$mtn->get_file(\$data, $new_file_id);
$new_fh->print($data);
$old_fh->close();
$new_fh->close();
lib/perl/Preferences.pm
15101510
15111511
15121512
1513
1513
15141514
15151515
15161516
"close",
__("The external file comparison application field is\n"
. "invalid, please correct before attempting to resave."));
$dialog->run();
WindowManager->instance()->allow_input(sub { $dialog->run(); });
$dialog->destroy();
return;
}
mtn-browse
26072607
26082608
26092609
2610
2611
26102612
26112613
26122614
......
26232625
26242626
26252627
2626
2628
26272629
26282630
26292631
......
26392641
26402642
26412643
2642
2644
26432645
26442646
26452647
......
27122714
27132715
27142716
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
27282733
27292734
27302735
my($mtn, $parent) = @_;
my $wm = WindowManager->instance();
if ($user_preferences->{show_suspended})
{
if ($mtn->can(MTN_IGNORE_SUSPEND_CERTS))
__("Your version of Monotone does not support\n"
. "suspend certificates. I will adjusted your\n"
. "preferences accordingly."));
$dialog->run();
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
$user_preferences->{show_suspended} = 0;
eval
"warning",
"close",
__("Your preferences could not be saved:\n") . $@);
$dialog->run();
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
}
}
if ($severity == MTN_SEVERITY_WARNING)
{
$dialog = Gtk2::MessageDialog->new_with_markup
(undef,
["modal"],
"warning",
"close",
__x("Problem with monotone request, got:\n"
. "<b><i>{error_message}</i></b>\n"
. "This should not be happening!",
error_message => Glib::Markup::escape_text($message)));
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
$wm->reset_state();
die($message);
if (! $suppress_mtn_warnings)
{
$dialog = Gtk2::MessageDialog->new_with_markup
(undef,
["modal"],
"warning",
"close",
__x("Problem with monotone request, got:\n"
. "<b><i>{error_message}</i></b>\n"
. "This should not be happening!",
error_message => Glib::Markup::escape_text($message)));
$wm->allow_input(sub { $dialog->run(); });
$dialog->destroy();
$wm->reset_state();
die($message);
}
}
else
{

Archive Download the corresponding diff file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status