monotone-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Monotone-devel] Re: Commit without working copy


From: graydon hoare
Subject: [Monotone-devel] Re: Commit without working copy
Date: Sat, 04 Dec 2004 00:01:53 -0500
User-agent: Mozilla Thunderbird 0.8 (X11/20040913)

Grzegorz Jakacki wrote:

OK, thanks. Where should I look into the code if I want to add it?

I have to apologize for all the worried talk here today; I don't really know what the big deal is, this command only takes about 10 minutes to write. I just wrote it. if you stick this in commands.cc you should get mostly the behavior you want:

CMD(fcommit, "tree", "REVISION FILENAME [LOG_MESSAGE]",
    "commit change to a single file")
{
  if (args.size() != 2 && args.size() != 3)
    throw usage(name);

  file_id old_fid, new_fid;
  revision_id old_rid, new_rid;
  manifest_id old_mid, new_mid;
  manifest_map old_man, new_man;
  file_data old_fdata, new_fdata;
  cert_value branchname;
  revision_data rdata;
  revision_set rev;
  change_set cs;

  string log_message("");
  base64< gzip< data > > gz_dat;
  base64< gzip< delta > > gz_del;
  file_path pth(idx(args, 1)());

  transaction_guard guard(app.db);
  packet_db_writer dbw(app);

  complete(app, idx(args, 0)(), old_rid);

  // find the old rev, manifest and file
  app.db.get_revision_manifest(old_rid, old_mid);
  app.db.get_manifest(old_mid, old_man);
  manifest_map::const_iterator i = old_man.find(pth);
  N(i != old_man.end(),
    F("cannot find file %s revision %s")
    % pth % old_rid);

  // fetch the new file input
  string s = get_stdin();
  pack(data(s), gz_dat);
  new_fdata = file_data(gz_dat);
  calculate_ident(new_fdata, new_fid);

  // diff and store the file edge
  old_fid = manifest_entry_id(i);
  app.db.get_file_version(old_fid, old_fdata);
  diff(old_fdata.inner(), new_fdata.inner(), gz_del);
  dbw.consume_file_delta(old_fid, new_fid,
                         file_delta(gz_del));

  // diff and store the manifest edge
  new_man = old_man;
  new_man[pth] = new_fid;
  calculate_ident(new_man, new_mid);
  diff(old_man, new_man, gz_del);
  dbw.consume_manifest_delta(old_mid, new_mid,
                             manifest_delta(gz_del));

  // build and store a changeset and revision
  cs.apply_delta(pth, old_fid, new_fid);
  rev.new_manifest = new_mid;
  rev.edges.insert(std::make_pair(old_rid,
                                  std::make_pair(old_mid, cs)));
  calculate_ident(rev, new_rid);
  write_revision_set(rev, rdata);
  dbw.consume_revision_data(new_rid, rdata);

  // take care of any extra certs
  guess_branch (old_rid, app, branchname);
  app.set_branch(branchname());

  if (args.size() == 3)
    log_message = idx(args, 2)();
  else
    get_log_message(rev, app, log_message);

  N(log_message.find_first_not_of(" \r\t\n") != string::npos,
    F("empty log message"));

  cert_revision_in_branch(new_rid, branchname, app, dbw);
  cert_revision_date_now(new_rid, app, dbw);
  cert_revision_author_default(new_rid, app, dbw);
  cert_revision_changelog(new_rid, log_message, app, dbw);

  // finish off
  guard.commit();
}

if you like I can add this as a "standard" monotone command, though it seems a bit special-purpose.. there is certainly some background pressure to overhaul monotone's command-line interface a bit. I was hoping to get around to that sometime after all these extra branches are integrated.

-graydon




reply via email to

[Prev in Thread] Current Thread [Next in Thread]