App-UpdateConfig

 view release on metacpan or  search on metacpan

script/update_config  view on Meta::CPAN

sub export_fragments {
  my ($fragments, $dir_confs) = split_config_files(get_data_section());
  for my $file (sort keys %{$fragments}) {
    my %conf = parse_file_conf($fragments->{$file}, $file, $dir_confs);
    my ($own, $content, $own_lines) = parse_directives($fragments->{$file});
    my $inherited = get_inherited_conf($file, $dir_confs);
    my @header = ('FILENAME '.get_target($file, \%conf));
    push @header, "GUARD SUFFIX $conf{guard_suffix}"
        if exists $conf{guard_suffix} and not exists $own->{guard_suffix};
    for my $d (sort keys %DIRECTIVES) {
      my ($key, $multiple) = @{$DIRECTIVES{$d}}{qw(key multiple)};
      next if not defined $key or $TARGET_KEYS{$key} or $key eq 'guard_suffix';
      next if not exists $inherited->{$key} or not exists $conf{$key};
      next if exists $own->{$key} and not $multiple;
      push @header,
          map { format_directive($d, $_) } $multiple ? @{$inherited->{$key}} : $inherited->{$key};
    }
    for my $line (@{$own_lines}) {
      my ($d) = $line =~ m/^(${DIRECTIVE_RE})/;
      push @header, $line if not $TARGET_KEYS{$DIRECTIVES{$d}{key} // ''};
    }
    $content = join('', map { "${_}\n" } @header).$content;
    $file =~ s/^\.//;
    $file =~ s{/|,}{_}g;
    print "Exporting: $file\n";
    write_file($file, $content) or die "Cannot write file '$file': $!\n";
  }
  return;
}

# Prints on STDOUT our own script, followed by all the given fragments, so that
# they are embedded in its __DATA__ section.
sub pack_fragments {
  my ($config_files) = @_;
  print read_file(catfile($FindBin::RealBin, $FindBin::RealScript));
  for my $file (sort by_fragment_order keys %{$config_files}) {
    my $content = $config_files->{$file};
    # The next "@@" header must start on its own line.
    $content .= "\n" if $content ne '' and $content !~ m/\n\z/;
    print "@@ ${file}\n${content}";
  }
  return;
}

# Returns true if all the REQUIRE guards of the fragment are verified.
sub check_requirements {
  my ($conf, $display_name) = @_;
  for my $r (@{$conf->{require}}) {
    my ($expr, $reason) = split /\s*#\s*/, $r, 2;
    next if eval $expr;  ## no critic (ProhibitStringyEval)
    die "Error while executing 'require' guard for ${display_name} '${expr}': $@.\n" if $@;
    printf "Skipping %s due to require guard%s\n", $display_name, ($reason ? ': '.$reason : '')
        unless $flags{silent};
    return 0;
  }
  return 1;
}

# Writes the new content of the target file and executes the POST UPDATE
# command if any.
sub update_target {
  my ($mode, $out_path, $before, $new_content, $after, $conf) = @_;
  if (exists $conf->{symlink}) {
    write_symlink($out_path, $conf->{symlink});
  } elsif ($conf->{entire_file} or $conf->{merge}) {
    write_content($mode, $out_path, $new_content, $conf);
  } else {
    my $content = $before.$conf->{start_marker}.$new_content.$conf->{end_marker}.$after;
    write_content($mode, $out_path, $content, $conf);
  }
  if ($conf->{post_update}) {
    my $cmd = $conf->{post_update} =~ s/\$@/$out_path/gr;
    system $cmd;
  }
  return;
}

# Returns the current content of the target of the given fragment (from
# prepare_fragment), split in four parts: the content before the managed part,
# the current and new versions of the managed part, and the content after it.
sub get_contents {
  my ($fragment) = @_;
  my ($mode, $in_path, $conf) = @{$fragment}{qw(mode in_path conf)};
  return ('', describe_symlink_target($in_path), "-> $conf->{symlink}\n", '')
      if exists $conf->{symlink};
  if (not $conf->{merge}) {
    my ($before, $old_content, $after) = read_content($mode, $in_path, $conf);
    return ($before, $old_content, $conf->{content}, $after);
  }
  my $module = $MERGE_FORMATS{$conf->{merge}}{module};
  load_module($module) if $module;
  my $old = read_merge_state($fragment);
  return ('', merge_content($mode, $in_path, $conf, $old), '');
}

# Returns the given $path resolved relative to the $base path. Both are relative
# to the home directory (an empty $base is the home directory itself), unless
# they are absolute. A $path starting with `~` is relative to the home
# directory, whatever the $base.
sub resolve_path {
  my ($base, $path) = @_;
  return $path if $path =~ m{^/};
  if ($path =~ m{^~(?:/+(.*))?$}) {
    return $1 // '';
  }
  return $path if $base eq '';
  return catfile($base, $path);
}

# Returns the given component of the name of a fragment (its base name or, with
# the MIRROR directive, one of its directories), as it is used in its target:
# without its suffix between brackets and with a `dot_` prefix replaced by a
# dot (as hidden files are ignored in the configuration directory). $name is
# the name of the fragment, used in error messages.
sub get_target_name {
  my ($name, $part) = @_;
  my $clean = clean_output_path($part);
  die "Cannot use '${part}' in the target of '${name}', its name is only a guard suffix.\n"
      if $clean eq '';
  return $clean =~ s/^dot_/./r;
}



( run in 0.597 second using v1.01-cache-2.11-cpan-145b269f2f3 )