04bb0d53e914d5574114ca4371d82badb6a95c93
[nethome.git] / bin / xbelnormalize
1 #! /usr/bin/perl
2 #
3 # $Id$
4 #
5 # Normalize the .xbel file for cvs(1)/diff(1) etc.
6 # Removes any variable data from the file.
7 # Reencodes the file to utf-8.
8
9
10 use strict;
11 use warnings;
12
13 require XML::Twig;
14 use File::Temp qw(tempfile);
15
16
17 my $opt_replace;
18 # No &Getopt::Long::GetOptions as we need to distinguish '-i' and '-iext'.
19 while (@ARGV) {
20         last if $ARGV[0]!~/^-/;
21         local $_=shift @ARGV;
22         if ($_ eq "-h" || $_ eq "--help") {
23                 print <<"HERE";
24 @{[ '$Id$' ]}
25
26 Syntax: $0 [-i[<extension>]] [<file.xbel>]
27
28 -i[<extension>] edit the file in place (makes backup if extension supplied)
29 HERE
30                 exit;
31         }
32         if (s/^-i//) {
33                 $opt_replace=$_;
34                 next;
35         }
36         if ($_ eq "--") {
37                 last;
38         }
39         die "Invalid argument: $_\n";
40 }
41 die "Too many files\n" if 1<@ARGV;
42
43 my $twig=XML::Twig->new(
44         "pretty_print"=>"indented",
45         "output_encoding"=>"utf-8",
46         "ignore_elts"=>{
47                 "time_visited"=>1,
48                 "time_added"=>1,
49                 "time_modified"=>1,
50                 "smart_site_data"=>1,
51         },
52         "twig_roots"=>{
53                 "metadata"=>sub { $_->delete() if !$_->has_children(); },
54                 "info"    =>sub { $_->delete() if !$_->has_children(); },
55                 "folder"=>sub { $_->del_att("folded"); },
56                 "xbel"  =>sub { $_->del_att("folded"); },
57         },
58 );
59 my $filename;
60 if (!($filename=$ARGV[0])) {
61         $twig->parse(\*STDIN);
62         $twig->flush();
63         exit;
64 }
65 $twig->parsefile($filename);
66 my $tmpname;
67 my $dstfh;
68 if (!defined $opt_replace) {
69         $dstfh=\*STDOUT;
70 } else {
71         if (!$opt_replace) {
72                 (undef(),$tmpname)=tempfile("DIR"=>".");
73         } elsif ($opt_replace=~/[*]/) {
74                 ($tmpname=$opt_replace)=~s/[*]/$filename/g;
75         } else {
76                 $tmpname=$filename.$opt_replace;
77         }
78         rename($filename,$tmpname) or die "Error renaming \"$filename\" to \"$tmpname\": $!";
79         open $dstfh,">",$filename or die "Error opening target file \"$filename\": $!";
80 }
81 $twig->flush($dstfh);
82 if (defined $opt_replace) {
83         close $dstfh or die "Error closing target file \"$filename\": $!";
84         if (!$opt_replace) {
85                 unlink $tmpname or die "Error deleting temporary file \"$tmpname\": $!";
86         }
87 }