Blame tests/corrupt-repo-ref.js

Packit Service 2a3f3d
#!/usr/bin/env gjs
Packit Service 2a3f3d
//
Packit Service 2a3f3d
// Copyright (C) 2014 Colin Walters <walters@verbum.org>
Packit Service 2a3f3d
//
Packit Service 2a3f3d
// SPDX-License-Identifier: LGPL-2.0+
Packit Service 2a3f3d
//
Packit Service 2a3f3d
// This library is free software; you can redistribute it and/or
Packit Service 2a3f3d
// modify it under the terms of the GNU Lesser General Public
Packit Service 2a3f3d
// License as published by the Free Software Foundation; either
Packit Service 2a3f3d
// version 2 of the License, or (at your option) any later version.
Packit Service 2a3f3d
//
Packit Service 2a3f3d
// This library is distributed in the hope that it will be useful,
Packit Service 2a3f3d
// but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 2a3f3d
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 2a3f3d
// Lesser General Public License for more details.
Packit Service 2a3f3d
//
Packit Service 2a3f3d
// You should have received a copy of the GNU Lesser General Public
Packit Service 2a3f3d
// License along with this library; if not, write to the
Packit Service 2a3f3d
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit Service 2a3f3d
// Boston, MA 02111-1307, USA.
Packit Service 2a3f3d
Packit Service 2a3f3d
const GLib = imports.gi.GLib;
Packit Service 2a3f3d
const Gio = imports.gi.Gio;
Packit Service 2a3f3d
const OSTree = imports.gi.OSTree;
Packit Service 2a3f3d
Packit Service 2a3f3d
let repoPathArg = ARGV[0];
Packit Service 2a3f3d
let refToCorrupt = ARGV[1];
Packit Service 2a3f3d
Packit Service 2a3f3d
let repo = OSTree.Repo.new(Gio.File.new_for_path(repoPathArg));
Packit Service 2a3f3d
Packit Service 2a3f3d
repo.open(null);
Packit Service 2a3f3d
Packit Service 2a3f3d
function listObjectChecksumsRecurse(dir, allObjects) {
Packit Service 2a3f3d
    dir.ensure_resolved();
Packit Service 2a3f3d
    allObjects[dir.tree_get_contents_checksum() + '.dirtree'] = true;
Packit Service 2a3f3d
    allObjects[dir.get_checksum() + '.dirmeta'] = true;
Packit Service 2a3f3d
    let e = dir.enumerate_children('standard::name,standard::type', 0, null);
Packit Service 2a3f3d
    let info;
Packit Service 2a3f3d
    while ((info = e.next_file(null)) != null) {
Packit Service 2a3f3d
	let child = e.get_child(info);
Packit Service 2a3f3d
	child.ensure_resolved();
Packit Service 2a3f3d
	print(info.get_name() + " is " + info.get_file_type());
Packit Service 2a3f3d
	if (info.get_file_type() == Gio.FileType.DIRECTORY) {
Packit Service 2a3f3d
	    listObjectChecksumsRecurse(child, allObjects);
Packit Service 2a3f3d
	} else {
Packit Service 2a3f3d
	    allObjects[child.get_checksum() + '.filez'] = true;
Packit Service 2a3f3d
	}
Packit Service 2a3f3d
    } 
Packit Service 2a3f3d
    e.close(null);
Packit Service 2a3f3d
} 
Packit Service 2a3f3d
Packit Service 2a3f3d
let [,root,commit] = repo.read_commit(refToCorrupt, null);
Packit Service 2a3f3d
let allObjects = {};
Packit Service 2a3f3d
allObjects[commit + '.commit'] = true;
Packit Service 2a3f3d
listObjectChecksumsRecurse(root, allObjects);
Packit Service 2a3f3d
let i = 0;
Packit Service 2a3f3d
for (let v in allObjects) 
Packit Service 2a3f3d
    i++;
Packit Service 2a3f3d
print("commit " + commit + " refers to " + i + " objects");
Packit Service 2a3f3d
let offset = GLib.random_int_range(0, i);
Packit Service 2a3f3d
let objectToCorrupt = null;
Packit Service 2a3f3d
for (let v in allObjects) {
Packit Service 2a3f3d
    if (offset <= 0) {
Packit Service 2a3f3d
	objectToCorrupt = v;
Packit Service 2a3f3d
	break;
Packit Service 2a3f3d
    }
Packit Service 2a3f3d
    offset--;
Packit Service 2a3f3d
}
Packit Service 2a3f3d
print("Choosing " + objectToCorrupt + " to corrupt");
Packit Service 2a3f3d
Packit Service 2a3f3d
let loosePath = repo.get_path().resolve_relative_path('objects/' + objectToCorrupt.substring(0, 2) + "/" + objectToCorrupt.substring(2));
Packit Service 2a3f3d
Packit Service 2a3f3d
let iostream = loosePath.open_readwrite(null);
Packit Service 2a3f3d
let info = iostream.query_info('standard::size', null);
Packit Service 2a3f3d
let size = info.get_size();
Packit Service 2a3f3d
let datain = Gio.DataInputStream.new(iostream.get_input_stream());
Packit Service 2a3f3d
let dataout = Gio.DataOutputStream.new(iostream.get_output_stream());
Packit Service 2a3f3d
let bytesToChange = 10;
Packit Service 2a3f3d
let status = "";
Packit Service 2a3f3d
var bytesChanged = {}
Packit Service 2a3f3d
for (i = 0; i < bytesToChange; i++) {
Packit Service 2a3f3d
    let byteOffsetToCorrupt;
Packit Service 2a3f3d
    do {
Packit Service 2a3f3d
        byteOffsetToCorrupt = GLib.random_int_range(0, size);
Packit Service 2a3f3d
    } while (byteOffsetToCorrupt in bytesChanged);
Packit Service 2a3f3d
    iostream.seek(byteOffsetToCorrupt, GLib.SeekType.SET, null);
Packit Service 2a3f3d
    let inbyte = datain.read_byte(null);
Packit Service 2a3f3d
    let outbyte = (inbyte + 1) % 255;
Packit Service 2a3f3d
    dataout.put_byte(outbyte, null);
Packit Service 2a3f3d
    bytesChanged[byteOffsetToCorrupt] = byteOffsetToCorrupt;
Packit Service 2a3f3d
    status += "Changed byte offset " + byteOffsetToCorrupt + " from " + inbyte + " to " + outbyte + "\n";
Packit Service 2a3f3d
}
Packit Service 2a3f3d
dataout.flush(null);
Packit Service 2a3f3d
iostream.close(null);
Packit Service 2a3f3d
Packit Service 2a3f3d
print(status);
Packit Service 2a3f3d
let successFile = Gio.File.new_for_path('corrupted-status.txt');
Packit Service 2a3f3d
successFile.replace_contents(status, null, false, 0, null);