# ================================================================
Readonly my $VERSION => "0.8.1"; ## Please keep this current!
Readonly my $VERSMIN => "-" x length($VERSION);
+Readonly my $PROGDIR => dirname($0);
Readonly my $PROGNAME => basename($0);
Readonly my $WORKDIR => getcwd();
Readonly my $USAGE_SHORT => "$PROGNAME <--help|[OPTIONS] <path to upstream tree>>";
## hunks : Arrayref with the Hunks, stored in %hHunk instances
## output : Arrayref with the lines of the final patch
## part : local relative file path
- ## patch : WORKDIR/patches/<part>.patch (With / replaced by _ in <part>)
+ ## patch : PROGDIR/patches/<part>.patch (With / replaced by _ in <part>)
## source : WORKDIR/<part>
## target : UPSTREAM/<part>
## )
# === 5) Check for useful blank line additions ====================
check_blanks and hunk_is_useful and prune_hunk or next;
-
+
# === 6) Check for 'elogind' => 'systemd' reverts =================
check_name_reverts and hunk_is_useful and prune_hunk or next;
# --- Splice all include insertions that are marked for splicing ---
# ---------------------------------------------------------------------
splice_includes;
-
+
# ---------------------------------------------------------------------
# --- Go through all hunks for a last prune and check ---
# ---------------------------------------------------------------------
prune_hunk and ++$have_hunk;
}
-
+
# If we have at least 1 useful hunk, create the output and tell the user what we've got.
$have_hunk
and build_output # (Always returns 1)
and printf("%d Hunk%s\n", $have_hunk, $have_hunk > 1 ? "s" : "")
or print("clean\n");
-
+
# Shell and meson files must be unprepared. See unprepare_shell()
$hFile{source} =~ m/\.pwx$/ and unprepare_shell;
hunks => [ ],
output => [ ],
part => "$part",
- patch => "patches/${patch}.patch",
+ patch => "$PROGDIR/patches/${patch}.patch",
source => "$WORKDIR/$part",
target => "$tgt"
);
return 0;
}
-
# -----------------------------------------------------------------------
# --- Writes $hFile{output} from all useful $hFile{hunks}. ---
# --- Important: No more checks, just do it! ---
for (my $pos = 0; $pos < $hFile{count}; ++$pos) {
$hHunk = $hFile{hunks}[$pos]; ## Global shortcut
$hHunk->{useful} or next; ## And the skip of the useless.
-
+
# --- Add the header line -----------------
# -----------------------------------------
push(@{$hFile{output}}, get_hunk_head(\$offset));
-
+
# --- Add the hunk lines ------------------
# -----------------------------------------
for my $line (@{$hHunk->{lines}}) {
push(@{$hFile{output}}, $line);
}
} ## End of walking the hunks
-
+
return 1;
}
-
# -----------------------------------------------------------------------
# --- Check that useful blank line additions aren't misplaced. ---
# ---- Note: Sometimes the masks aren't placed correctly, and the diff---
for (my $i = 0; $i < $hHunk->{count}; ++$i) {
my $line = \$hHunk->{lines}[$i]; ## Shortcut
-
+
if ( ($$line =~ m/^\+\s*$/)
&& ($i > 0)
&& ($hHunk->{lines}[$i-1] =~ m/^[ -+]#if\s+[01].*elogind/) ) {
next;
}
}
-
+
return 1;
}
-
# -----------------------------------------------------------------------
# --- Check comments we added for elogind specific information. ---
# --- These are all comments, and can be both single and multi line. ---
return 1;
}
-
# -----------------------------------------------------------------------
# --- Check for attempts to remove elogind_*() special function calls. --
# --- We have som special functions, needed oly by elogind. ---
return 1;
}
-
# -----------------------------------------------------------------------
# --- Check hunk for include manipulations we must step in ---
# --- This is basically read_include(), but this time we actually act ---
# We must know when "needed by elogind blocks" start
my $in_elogind_block = 0;
-
+
# The simple undo check will fail, if we do at least one at once.
# Delay the undoing of the removals until after the hunk was checked.
my %undos = ();
return 1;
}
-
# -----------------------------------------------------------------------
# --- Check for attempts to revert 'elogind' to 'systemd' ---
# --- Note: We only check for single line reverts like: ---
for (my $i = 0; $i < $hHunk->{count}; ++$i) {
my $line = \$hHunk->{lines}[$i]; ## Shortcut
-
+
defined($$line) or return hunk_failed("check_name_reverts: Line " . ($i + 1) . "/$hHunk->{count} is undef?\n");
# Note down removals
$hRemovals{$1}{line} = $i;
next;
}
-
+
# Check Additions
# ---------------------------------
if ($$line =~ m/^\+\s*(.*systemd.*)\s*$/) {
- my $our_text = $1;
- $our_text =~ s/systemd/elogind/g;
-
+ my $replace_text = $1;
+ my $our_text_long = $replace_text;
+ my $our_text_short = $our_text_long;
+ $our_text_long =~ s/systemd-logind/elogind/g;
+ $our_text_short =~ s/systemd/elogind/g;
+
+ # There is one speciality:
+ # In some meson files, we need the variable "systemd_headers".
+ # This refers to the systemd API headers that get installed,
+ # and must therefore not be renamed to elogind_headers.
+ $our_text_short =~ s/elogind_headers/systemd_headers/g;
+
# If this is a simple switch, undo it:
- if (defined($hRemovals{$our_text})) {
- substr($hHunk->{lines}[$hRemovals{$our_text}{line}], 0, 1) = " ";
+ if ( defined($hRemovals{$our_text_short})
+ || defined($hRemovals{$our_text_long }) ) {
+ defined($hRemovals{$our_text_short} )
+ and substr($hHunk->{lines}[$hRemovals{$our_text_short}{line}], 0, 1) = " "
+ or substr($hHunk->{lines}[$hRemovals{$our_text_long }{line}], 0, 1) = " ";
splice(@{$hHunk->{lines}}, $i--, 1);
$hHunk->{count}--;
next;
}
-
+
# Otherwise replace the addition with our text. ;-)
- $$line =~ s/^\+(\s*).*systemd.*(\s*)$/+${1}${our_text}${2}/;
+ $our_text_long eq $replace_text
+ and $$line =~ s/^\+(\s*).*systemd.*(\s*)$/+${1}${our_text_short}${2}/
+ or $$line =~ s/^\+(\s*).*systemd.*(\s*)$/+${1}${our_text_long }${2}/;
}
}
-
+
return 1;
}
-
# -----------------------------------------------------------------------
# --- Checkout the given refid on $upstream_path ---
# --- Returns 1 on success, 0 otherwise. ---
# It is completely in order to not wanting to checkout a specific commit.
defined($commit) and length($commit) or return 1;
-
+
# Save the previous commit
$previous_commit = qx(cd $upstream_path ; git rev-parse --short HEAD 2>&1);
if ($?) {
$tgt_len++;
}
}
-
+
# If an offset reference was given, add back the size diff
defined($offset)
and $$offset += $tgt_len - $src_len;
} else {
die("$out can not be opened for writing! [$!]");
}
-
+
# The temporary file is our new source
$hFile{source} = $out;
return 1;
}
-
# -----------------------------------------------------------------------
# --- Unprepare shell (and meson) files after our processing ---
# --- In prepare_shell() we have commented in all content between our ---
return 1;
}
-
# -----------------------------------------------------------------------
# --- Analyze the hunk and map all include changes ---
# --- The gathered knowledge is used in check_includes(), see there ---
return 1;
}
-
# -----------------------------------------------------------------------
# --- Splice all includes that were marked for splicing. ---
# --- This is not as easy as it seems. It can be, that if we just go ---
# --- worse, the splicing being attempted out of bounds. ---
# -----------------------------------------------------------------------
sub splice_includes {
-
+
# First build a tree of the includes to splice:
my %incMap = ();
for my $inc (keys %hIncs) {
if ($hIncs{$inc}{insert}{spliceme}) {
my $hId = $hIncs{$inc}{insert}{hunkid};
my $lId = $hIncs{$inc}{insert}{lineid};
-
+
# Sanity checks:
$hId > -1 or print "splice_includes : Inc $inc has Hunk Id -1!\n" and next;
if ( -1 == $lId ) {
hunk_failed("splice_includes: $inc line id $lId/$hFile{hunks}[$hId]{count}!");
next;
}
-
+
# Record the include line
$incMap{$hId}{$lId} = 1;
}
return 1;
}
-
# Callback function for File::Find
sub wanted {
-f $_ and ( (0 == $have_wanted)
and push @source_files, $File::Find::name;
return 1;
}
-