From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jonathan Nieder Subject: [PATCH 10/22] branch.c: use ref transaction for all ref updates Date: Tue, 2 Sep 2014 14:04:05 -0700 Message-ID: <20140902210405.GK18279@google.com> References: <20140820231723.GF20185@google.com> <20140826000354.GW20185@google.com> <20140826221448.GY20185@google.com> <20140827002804.GA20185@google.com> <20140902205841.GA18279@google.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Cc: Ronnie Sahlberg , "git@vger.kernel.org" , Michael Haggerty To: Junio C Hamano X-From: git-owner@vger.kernel.org Tue Sep 02 23:04:15 2014 Return-path: Envelope-to: gcvg-git-2@plane.gmane.org Received: from vger.kernel.org ([209.132.180.67]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1XOvFO-00031W-3L for gcvg-git-2@plane.gmane.org; Tue, 02 Sep 2014 23:04:14 +0200 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755227AbaIBVEJ (ORCPT ); Tue, 2 Sep 2014 17:04:09 -0400 Received: from mail-pd0-f172.google.com ([209.85.192.172]:49773 "EHLO mail-pd0-f172.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755208AbaIBVEI (ORCPT ); Tue, 2 Sep 2014 17:04:08 -0400 Received: by mail-pd0-f172.google.com with SMTP id z10so9499762pdj.31 for ; Tue, 02 Sep 2014 14:04:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; bh=LBK1GLIBFc3xCb9zzOqhcUveOrzzzxDvF2agHqab1es=; b=BLjvfLgFzFNw4wpcI2sLkH7lO10SDk7bokNJ1qkA+NmBsbmL/qAuASu7zYdpqK3l7m YMYEsb/Rt5HR0OxgwL0TPSVziLydRr0xjHw8wQq5Lxgi/4C/O/z4ONahGy5/qdZSEyJr QSaiKWycqH7BDdT8LLuJE2tMpRxRxslM3t1ShaOM7S4jzCkavs4A3C6pnNjU0gfTY1OE YU3lUqHIXEeOl3+LFWTx/Ouq5/YyMscRo5RAZhx1GTn2MAFwbNn1SgWPBNh/d6teK7Oj RwRc3GLBK5FrEcexEGkpbHv+c+yP32QuNl8b9JWqDcozCSrV5PSvr1ai347udRNhHDlJ Y8aw== X-Received: by 10.70.128.195 with SMTP id nq3mr7599586pdb.158.1409691848171; Tue, 02 Sep 2014 14:04:08 -0700 (PDT) Received: from google.com (aiede.mtv.corp.google.com [172.27.69.120]) by mx.google.com with ESMTPSA id y4sm6840063pdm.1.2014.09.02.14.04.06 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Tue, 02 Sep 2014 14:04:07 -0700 (PDT) Content-Disposition: inline In-Reply-To: <20140902205841.GA18279@google.com> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Archived-At: From: Ronnie Sahlberg Date: Wed, 16 Apr 2014 16:21:53 -0700 Change create_branch to use a ref transaction when creating the new branch. This also fixes a race condition in the old code where two concurrent create_branch could race since the lock_any_ref_for_update/write_ref_sha1 did not protect against the ref already existing. I.e. one thread could end up overwriting a branch even if the forcing flag is false. Signed-off-by: Ronnie Sahlberg Reviewed-by: Michael Haggerty Signed-off-by: Jonathan Nieder --- branch.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/branch.c b/branch.c index 660097b..37ac555 100644 --- a/branch.c +++ b/branch.c @@ -226,7 +226,6 @@ void create_branch(const char *head, int force, int reflog, int clobber_head, int quiet, enum branch_track track) { - struct ref_lock *lock = NULL; struct commit *commit; unsigned char sha1[20]; char *real_ref, msg[PATH_MAX + 20]; @@ -285,15 +284,6 @@ void create_branch(const char *head, die(_("Not a valid branch point: '%s'."), start_name); hashcpy(sha1, commit->object.sha1); - if (!dont_change_ref) { - lock = lock_any_ref_for_update(ref.buf, NULL, 0, NULL); - if (!lock) - die_errno(_("Failed to lock ref for update")); - } - - if (reflog) - log_all_ref_updates = 1; - if (forcing) snprintf(msg, sizeof msg, "branch: Reset to %s", start_name); @@ -301,13 +291,26 @@ void create_branch(const char *head, snprintf(msg, sizeof msg, "branch: Created from %s", start_name); + if (reflog) + log_all_ref_updates = 1; + + if (!dont_change_ref) { + struct ref_transaction *transaction; + struct strbuf err = STRBUF_INIT; + + transaction = ref_transaction_begin(&err); + if (!transaction || + ref_transaction_update(transaction, ref.buf, sha1, + null_sha1, 0, !forcing, &err) || + ref_transaction_commit(transaction, msg, &err)) + die("%s", err.buf); + ref_transaction_free(transaction); + strbuf_release(&err); + } + if (real_ref && track) setup_tracking(ref.buf + 11, real_ref, track, quiet); - if (!dont_change_ref) - if (write_ref_sha1(lock, sha1, msg) < 0) - die_errno(_("Failed to write ref")); - strbuf_release(&ref); free(real_ref); } -- 2.1.0.rc2.206.gedb03e5